LeetCode 18 四数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

示例:

给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

满足要求的四元组集合为:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

分析:

如果是两数和问题,可以采用排序+双指针法,复杂度为o(nlogn)

而这个问题是四数和,所以要尽可能的转化为两数和问题,考虑在搜索的过程中如何剪枝。

首先肯定要固定前两个数,如果先对数组进行一次排序,就很容易得出如下剪枝方案:

设数组为nums,第一个数下标为i,第二数下标为j,数组的长度为len

nums[i]+nums[len-3]+nums[len-2]+nums[len-1] < target 直接i+1

nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target 直接退出循环

nums[i]+nums[j]+nums[len-2]+nums[len-1] < target 直接j+1

nums[i]+nums[j]+nums[j+1]+nums[j+2]>target 直接退出循环

固定前两个数后就转换为了两数和问题。

还有一个问题就是不能有重复的集合,因此在对四个数的进行遍历的时候,都需要考虑与相应的前一位数是否相同,如果相同就应该直接跳过,不然就会出现重复的问题。

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());
        int length = nums.size();
        for(int i = 0 ; i < length - 3 ; i ++ )
        {
            if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target) break;
            if(i > 0 && nums[i] == nums[i-1]) continue;
            if(nums[i] + nums[length-3] + nums[length-2] + nums[length - 1] < target) continue;
            for(int j = i + 1 ; j < length - 2 ; j ++ )
            { 
                if(nums[i]+nums[j]+nums[j+1]+nums[j+2] > target) break;
                if(j > i + 1 && nums[j] == nums[j-1]) continue;
                if(nums[i]+nums[j]+nums[length-2]+nums[length-1] < target) continue;
                int t = target - nums[i] - nums[j];
                int left = j + 1;
                int right = length - 1;
                while(left < right)
                {
                    if(nums[left] + nums[right] > t) right--;
                    else if(nums[left] + nums[right] < t) left++;
                    else{
                        vector<int> res;
                        res.push_back(nums[i]);
                        res.push_back(nums[j]);
                        res.push_back(nums[left]);
                        res.push_back(nums[right]);
                        result.push_back(res);
                        do{left++;}while(nums[left]==nums[left-1]);
                        do{right--;}while(nums[right]==nums[right+1]);
                    }
                }
            }
        }
        return result;
    }
};

猜你喜欢

转载自blog.csdn.net/yjr3426619/article/details/80966657