审题
给定一个包含 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 2 ) O(n^2) O(n2)解决这道题,即在外循环用一个双指针,在内循环也用一个双指针,但是对于外面的边界条件始终是想不出来,后来忍不住看了一眼官方题解,好家伙,官方的题解都是 O ( n 3 ) O(n^3) O(n3),于是彻底打消了两个双指针的想法改为二重循环遍历四个数字中的第一个和最后一个元素,内部两个元素依旧是采用双指针的办法。
代码实现
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> fin;
if ( nums.size()<4 ) return fin;
int n=nums.size();
int sum=nums[0]+nums[1]+nums[2]+nums[3];
sort(nums.begin(), nums.end());
for ( int i=0; i<n-3; i++ ) {
for ( int j=n-1; j>i+2; j-- ) {
int m=j-1;
int k=i+1;
while ( k<m ) {
sum=nums[i]+nums[k]+nums[m]+nums[j];
if ( sum == target ) {
vector<int> tempvec;
tempvec.push_back(nums[i]);
tempvec.push_back(nums[k]);
tempvec.push_back(nums[m]);
tempvec.push_back(nums[j]);
fin.push_back(tempvec);
while ( nums[k] == nums[k+1] && k<m ) k++;
while ( nums[m] == nums[m-1] && k<m ) m--;
k++;
} else if ( sum > target ) {
m--;
} else {
k++;
}
}
}
}
set<vector<int>> s(fin.begin(), fin.end());
fin.assign(s.begin(),s.end());
return fin;
}
};
在这段代码中,值得注意的是,我为了去重,并没有像Leetcode上大多数题解一样设定许多循环去检查数有没有变化,而是直接将数据保存到了set里再转到vector…算是偷了个小懒,好处就是逻辑清晰了一些吧。
反思
这几道数组题,都是对双指针的应用,熟练掌握其用法,10min内搞定一道不是问题。