题目链接:https://leetcode.com/problems/4sum/
Given an array S of n integers, are there elements a, b, c, 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:
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; };