Skip to content

Latest commit

 

History

History
107 lines (95 loc) · 3.63 KB

18. 4Sum.md

File metadata and controls

107 lines (95 loc) · 3.63 KB

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(n^3), 空间复杂度O(n)
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        
        unordered_set<string> us;
        for(int i = 0; i < n - 3; i++) {
            for(int j = i + 1; j < n - 2; j++) {
                int left = j + 1, right = n - 1;
                while(left < right) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum > target) right--;
                    else if(sum < target) left++;
                    else {
                        us.insert(to_string(nums[i]) + " " + to_string(nums[j]) + " " + 
                                  to_string(nums[left]) + " " + to_string(nums[right]));
                        left++, right--;
                    }
                }
            }
        }
        
        vector<vector<int>> vec;
        for(string str : us) {
            istringstream iss(str);
            int a, b, c, d;
            iss >> a >> b >> c >> d;
            vec.push_back({a, b, c, d});
        }
        return vec;
    }
};

解法二:

//时间复杂度O(n^3), 空间复杂度O(1)
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        
        vector<vector<int>> vec;
        for(int i = 0; i < n - 3; i++) {
            while(i > 0 && i < n - 3 && nums[i] == nums[i - 1]) i++;//去重
            for(int j = i + 1; j < n - 2; j++) {
                while(j > i + 1 && j < n - 2 && nums[j] == nums[j - 1]) j++;//去重
                int left = j + 1, right = n - 1;
                while(left < right) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum > target) {
                        right--;
                        while(right > left && nums[right] == nums[right + 1]) right--;//去重
                    }
                    else if(sum < target) {
                        left++;
                        while(left < right && nums[left] == nums[left - 1]) left++;//去重
                    }
                    else {
                        vec.push_back({nums[i], nums[j], nums[left], nums[right]});
                        left++, right--;
                        while(left < right && nums[left] == nums[left - 1]) left++;
                        while(right > left && nums[right] == nums[right + 1]) right--;//去重
                    }
                }
            }
        }

        return vec;
    }
};

思路:

解法一与3数之和思路类似。外层的遍历变成了双重遍历。

解法二在遍历过程中加了去重检查,省掉了转换成字符串的步骤。

2019/09/20 18:50