[leetcode] 18. 4Sum 解题报告

题目链接:https://leetcode.com/problems/4sum/

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.

    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)

思路:一种最直接的方式是DFS暴力搜索,时间复杂度是O(n^4),这种方式肯定超时,所以我们需要寻找其他的方法。

枚举第一个和第二个数,然后寻找第三第四个数的问题就变成了2sum的问题。

在2sum问题中我们的目标是找到两个数的和等于一个给定的数,所以我们要用到左右指针,left = 0, right = len-1;因为使用左右指针需要数组有序,因此我们要首先对数组进行排序。

而左右指针的移动规律是:

1. 如果当前nums[left] + nums[right] > target,说明我们要想让其和等于target,则需要让right指针左移一位,因为当前和太大了

2. 如果当前nums[left] + nums[right] < target,说明我们要想让其和等于target,则需要让left指针右移一位,因为当前和太小了

3. 如果当前nums[left] + nums[right] = target,则可以保存结果,左右指针都移动一次。然后需要注意的就是去重,如果nums[left+1] = nums[left]或nums[right-1]==nums[right],

则必须跳过这些值,因为这些方案都已经搜索过了。

恩,思路大概就是这些,4sum比2sum多了一些第一个和第二个数也要去重的步骤。这种时间复杂度是O(n^3)。

代码如下:

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int len = nums.size(), i = 0;
        while(i < len -3)//枚举第一个数
        {
            int j = i+1;
            while(j < len -2)//枚举第二个数
            {
                int left = j+1, right = len-1;
                while(left < right)//寻找第三第四个数
                {
                    int val = nums[i] + nums[j] + nums[left] + nums[right];
                    if(val < target) left++;
                    else if(val > target) right--;
                    else if(nums[i] + nums[j] + nums[left] + nums[right] == target)//找到了一个解
                    {
                        vector<int> tem;
                        tem.push_back(nums[i]);
                        tem.push_back(nums[j]);
                        tem.push_back(nums[left]);
                        tem.push_back(nums[right]);
                        result.push_back(tem);
                        while(nums[left+1] == nums[left]) left++;//去重
                        while(nums[right-1] == nums[right]) right--;
                        left++;
                        right--;
                    }
                }
                
                while(nums[j+1] == nums[j]) j++;//第二个数的去重
                j++;
            }
            while(nums[i+1] == nums[i]) i++;//第一个数的去重
            i++;
        }
        return result;
    }
private:
    vector<vector<int>> result;
};


你可能感兴趣的:(LeetCode,array)