题目链接 主要类比三数之和,在此基础之上进行操作。
主要思路:三数之和是在确定第一个数字之后,采用双指针确定剩余两个数字,同样的,四数之和我们在确定第一个和第二个数字的基础上,再采用双指针确定剩余两个数字,从而使时间复杂度降为
O
(
n
3
)
O(n^3)
O(n3)。 剪枝:本题要剪枝一下,因为样例中四数之和会超出int范围,过不了。①确定第一个数字之后,如果
n
u
m
s
[
i
]
+
n
u
m
s
[
i
+
1
]
+
n
u
m
s
[
i
+
2
]
+
n
u
m
s
[
i
+
3
]
>
t
a
r
g
e
t
nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target
nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target,即
n
u
m
s
[
i
]
nums[i]
nums[i]和后面连续的三个数字之和已经大于target了,那么此数组中就不存在等于target的四元组,直接break。②确定第一个数字之后,如果
n
u
m
s
[
i
]
+
n
u
m
s
[
n
?
1
]
+
n
u
m
s
[
n
?
2
]
+
n
u
m
s
[
n
?
3
]
<
t
a
r
g
e
t
nums[i]+nums[n-1]+nums[n-2]+nums[n-3]<target
nums[i]+nums[n?1]+nums[n?2]+nums[n?3]<target,即针对
n
u
m
s
[
i
]
nums[i]
nums[i]和最后三个数字之和如果小于target,说明针对此nums[i]就没有符合条件的四元组等于target了,因为最大的都小于target了,那么就跳过continue,遍历下一个
n
u
m
s
[
i
]
nums[i]
nums[i]了。然后确定第二个数字之后,同样的方法剪枝。 其他细节详见代码。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
if(nums.size()<4)return ans;
sort(nums.begin(),nums.end());
int n = nums.size();
for(int i = 0;i<n-3;i++) {
if(i>0&&nums[i]==nums[i-1])continue;
if((long long)nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) break;
if((long long)nums[i]+nums[n-1]+nums[n-2]+nums[n-3]<target) continue;
for(int j = i+1;j<n-2;j++) {
if(j>i+1&&nums[j]==nums[j-1])continue;
if((long long)nums[i]+nums[j]+nums[j+1]+nums[j+2]>target)break;
if((long long)nums[i]+nums[j]+nums[n-1]+nums[n-2]<target)continue;
int left = j+1;
int right = n-1;
while(left<right){
int quard = nums[i]+nums[j]+nums[left]+nums[right];
if(quard==target){
ans.push_back({nums[i],nums[j],nums[left],nums[right]});
while(left<right&&nums[left+1]==nums[left])left++;
left++;
while(left<right&&nums[right-1]==nums[right])right--;
right--;
}
else if(quard<target) {
left++;
}
else {
right--;
}
}
}
}
return ans;
}
};
|