Skip to content
本页目录

0018-四数之和

https://leetcode.cn/problems/4sum

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n a、b、c 和 d 互不相同 nums[a] + nums[b] + nums[c] + nums[d] == target 你可以按 任意顺序 返回答案 。

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]] 示例 2:

输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]

提示:

1 <= nums.length <= 200 -10^9 <= nums[i] <= 10^9 -10^9 <= target <= 10^9

思路

仿照三数之和,多一层循环,4重指针

https://leetcode.cn/problems/4sum/solution/si-shu-zhi-he-by-leetcode-solution/

注意去重的时候,最后两个指针,只有sum满足条件的时候才能去重,不能遍历到一个相同的数就去重

参考代码

csharp
public class Solution {
    public IList<IList<int>> FourSum(int[] nums, int target) {
        List<IList<int>> result = new List<IList<int>>();
        Array.Sort(nums);
        //四个指针,最后两个往中间夹
        
        for(int i=0; i<nums.Length - 3; i++){
            if(i>0 && nums[i] == nums[i-1]){
                //跳过相同的数
                continue;
            }
            for(int j=i+1; j<nums.Length - 2; j++){
                if(j>i+1 && nums[j] == nums[j-1]){
                    //跳过第二个相同的数
                    continue;
                }
                //设置左右指针
                int left = j+1;
                int right = nums.Length - 1;
                //Console.WriteLine("calc {0} {1} {2} {3}",i,j,left,right);
                while(left < right){
                    //使用long防止溢出
                 	long sum = (long)nums[i] + (long)nums[j] + (long)nums[left] + (long)nums[right];
                    if(sum > target){ //如果和大于0,说明需要减少,right左移
                        right--;
                    }
                    else if(sum < target){
                        left++;
                    }
                    else{ 
                        //说明相等:加入结果集 并且同时移动两边指针
                        //同时移动两边指针是因为,移动一边之后,如果是同样的数字应该是跳过的,不同的数字后,sum肯定不会为0,所以要移动另外一边,才有可能sum为0
                        List<int> list = new List<int>();
                        list.Add(nums[i]);
                        list.Add(nums[j]);
                        list.Add(nums[left]);
                        list.Add(nums[right]);
                        result.Add(list);
                        
                        //去除右边重复数字
                        while(left < right && nums[right-1] == nums[right]){
                            right--;
                        }
                        //去除左边重复的数字
                        while(left < right && nums[left+1] == nums[left]){
                            left++;
                        }

                        left++;
                        right--;
                    }                    
                }
            }
        }        
        return result;
    }
}

Released under the MIT License.