题目
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200-109 <= nums[i] <= 109-109 <= target <= 109
代码展示
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(),nums.end());
int n=nums.size();
for(int i=0;i<n;i++){
if(i>0&&nums[i]==nums[i-1])continue;
for (int j = i + 1; j < n; ++j) {
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1;
int right = n - 1;
while (left < right) {
long long sum = static_cast<long long>(nums[i]) + nums[j] + nums[left] + nums[right];
if (sum < target) {
++left;
} else if (sum > target) {
--right;
} else {
result.push_back({nums[i], nums[j], nums[left], nums[right]});
while (left < right && nums[left] == nums[left + 1]) ++left;
while (left < right && nums[right] == nums[right - 1]) --right;
++left;
--right;
}
}
}
}
return result;
}
};
写者心得
四数之和的代码和三数之和基本上就是照猫画虎,不知道的或者感兴趣的可以去看三数之和,里面详细介绍了这个双指针循环所注意用的点和它每一个步骤的作用。但是其中有几个点,是我觉得应该需要注意的。问题是在三数之和里面都没有遇到的问题。因为是四数之和嘛,所以我最初的想法是把拨出来的那个数放在 left和right之间,是这样子就造成while循环没有办法正常运行的情况。所以就把多出来的这个数放在了left之前,那就完美的解决了问题。但是后面我又遇到了,他告诉我在sum整数溢出的情况,这让我无所适从,不过后面通过查询还是解决了问题。使用这个long long可以很好的解决整数溢出的情况。接下来再遇到什么五数之和,六数之和的时候,我想所有问题就可以迎刃而解,保证双指针循环不动,在left前方加多出来的数就可以了,当然那个所加的数必须得是循环,而不能够是单独的,也就是循环的嵌套,意思是你得加一个For循环,这个多加的for循环得注意,就是你得时刻谨记你要去过滤掉那些重复的数。所以得加一个if条件。
代码的逐行解释
-
初始化结果向量
vector<vector<int>> result;- 初始化一个二维向量
result,用于存储满足条件的四元组。
- 初始化一个二维向量
-
排序输入向量
sort(nums.begin(), nums.end());- 使用
sort函数对输入向量nums进行升序排序,方便后续的双指针操作。
- 使用
-
获取输入向量的大小
int n = nums.size();- 获取
nums的大小,存储在变量n中。
- 获取
-
外层循环
for (int i = 0; i < n; i++) {- 外层循环遍历
nums的每个元素,作为第一个数。
- 外层循环遍历
-
跳过重复的元素
if (i > 0 && nums[i] == nums[i - 1]) continue;- 如果当前元素
nums[i]与前一个元素nums[i - 1]相同,跳过当前迭代,避免产生重复的四元组。
- 如果当前元素
-
内层循环
for (int j = i + 1; j < n; ++j) {- 内层循环遍历从
i + 1开始的每个元素,作为第二个数。
- 内层循环遍历从
-
跳过重复的元素
if (j > i + 1 && nums[j] == nums[j - 1]) continue;- 如果当前元素
nums[j]与前一个元素nums[j - 1]相同,跳过当前迭代,避免产生重复的四元组。
- 如果当前元素
-
初始化双指针
int left = j + 1; int right = n - 1;- 初始化左指针
left和右指针right,分别指向j + 1和nums的最后一个元素。
- 初始化左指针
-
双指针法寻找四元组
while (left < right) {- 使用双指针法,当
left小于right时,继续循环。
- 使用双指针法,当
-
计算当前四个数的和
long long sum = static_cast<long long>(nums[i]) + nums[j] + nums[left] + nums[right];- 计算当前四个数的和
sum,使用long long类型防止溢出。
- 计算当前四个数的和
-
处理 sum 小于 target 的情况
if (sum < target) { ++left; }- 如果
sum小于target,说明需要更大的数,移动左指针left。
- 如果
-
处理 sum 大于 target 的情况
else if (sum > target) { --right; }- 如果
sum大于target,说明需要更小的数,移动右指针right。
- 如果
-
处理 sum 等于 target 的情况
else { result.push_back({nums[i], nums[j], nums[left], nums[right]}); while (left < right && nums[left] == nums[left + 1]) ++left; while (left < right && nums[right] == nums[right - 1]) --right; ++left; --right; }- 如果
sum等于target,找到一个满足条件的四元组,将其加入结果向量result中。 - 跳过重复的左指针元素,避免产生重复的四元组。
- 跳过重复的右指针元素,避免产生重复的四元组。
- 移动左指针和右指针,继续寻找下一个可能的四元组。
- 如果
-
返回结果
return result;- 返回结果向量
result。
- 返回结果向量
303

被折叠的 条评论
为什么被折叠?



