6 三数之和

📅 2026/7/19 18:26:02
6 三数之和
给你一个整数数组nums判断是否存在三元组[nums[i], nums[j], nums[k]]满足i ! j、i ! k且j ! k同时还满足nums[i] nums[j] nums[k] 0。请你返回所有和为0且不重复的三元组。注意答案中不可以包含重复的三元组。示例 1输入nums [-1,0,1,2,-1,-4] 输出[[-1,-1,2],[-1,0,1]] 解释 nums[0] nums[1] nums[2] (-1) 0 1 0 。 nums[1] nums[2] nums[4] 0 1 (-1) 0 。 nums[0] nums[3] nums[4] (-1) 2 (-1) 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意输出的顺序和三元组的顺序并不重要。示例 2输入nums [0,1,1] 输出[] 解释唯一可能的三元组和不为 0 。示例 3输入nums [0,0,0] 输出[[0,0,0]] 解释唯一可能的三元组和为 0 。思路1、判断参数的合法性。2、给数组排序计算数组长度。3、开始第一层循环定义为i从0循环到数组末尾。相同的元素每一层只能循环一次即判断i不等于0时nums[i]等于nums[i-1]就跳过这一次循环continue4、初始化第三层的移动指针kk指向数组的末尾nums.size()-1;5、进入第二层循环j从i1循环到数组末尾。同样相同的元素每一层只能循环一次判断j不等于i1时nums[j]等于nums[j-1]就跳过这一次循环continue6、进入第三层循环第三层循环从末尾开始由于第二层循环数字是越来越大的第三层移动指针应该越来越小。7、核心判断与结果收集在第三层循环中当j k时计算当前三元组的和sum nums[i] nums[j] nums[k]。如果sum 0说明找到了一个有效三元组。此时将[nums[i], nums[j], nums[k]]加入结果列表。随后需要移动指针以寻找其他可能的组合同时避免重复将j向右移动一位j并跳过所有与nums[j]相同的值直到遇到不同的元素以确保下一轮第二层循环的值是新的。同时将k向左移动一位k--并跳过所有与nums[k]相同的值直到遇到不同的元素。这一步是双指针收缩的关键它保证了在找到一组解后能高效地继续探索剩余空间。如果sum 0说明当前和偏小。由于数组已排序增大和的最直接方式是增大j即第二层循环的值。因此将j向右移动一位j。如果sum 0说明当前和偏大。减小和的最直接方式是减小k即第三层指针的值。因此将k向左移动一位k--。循环的终止条件是j k不再满足。当j与k相遇或交错时对于当前固定的i所有以nums[j]和nums[k]为组合的可能性都已探索完毕。此时第二层循环j会进入下一次迭代或者第一层循环i进入下一个值重复上述过程直到遍历完所有不重复的i。class Solution { public: vectorvectorint threeSum(vectorint nums) { int nnums.size(); if(n3) return {}; vectorvectorint ans; std::sort(nums.begin(),nums.end()); for(int i0;in;i){ if(i!0nums[i]nums[i-1]) continue; int kn-1; for(int ji1;jn;j){ if(j!i1nums[j]nums[j-1]) continue; while(kj){ if(nums[i]nums[j]nums[k]0) k--; else break; } if(nums[i]nums[j]nums[k]0j!k){ ans.push_back({nums[i],nums[j],nums[k]}); } } } return ans; } };