博客主页:Skylar Lin
望本文能够给您带来一定的帮助,如果有错误的地方敬请斧正!
新人博主🧑,希望多多支持🍺,还有好多库存和大家分享🎁。
转载需注明出处和原作🌹。
三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。
请你返回所有和为 0
且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
输入: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] 。
注意,输出的顺序和三元组的顺序并不重要。
初步想法
-
先进行排序,方便后面组成相同的三元组
-
使用
set
集合去重 -
三重循环
属于暴力法,部分测试用例超时。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
if(!n) return {};
int left = 1, right = 2;
//用 set 集合去重
set<vector<int> > st;
//三重循环
for(int i = 0; i < n; ){
while(left < n - 1){
while(right < n){
if(nums[i] + nums[left] + nums[right] == 0){
vector<int> temp = {nums[i], nums[left], nums[right]};
st.insert(temp);
}
right++;
}
left++;
right = left + 1;
}
left = (++i) + 1;
right = left + 1;
}
//将set集合中的内容赋给vector向量
vector<vector<int> > ans;
for(auto it : st){
ans.push_back(it);
}
return ans;
}
};
正确思路及解析
-
排序。跳出三重循环的框架,找到数值间的大小关系。
-
由于
a + b + c = 0
,二重循环往后枚举一位后会有a + b' + c' = 0
,且b' > b
,可推出c' < c
。 -
保持第二重循环不变,而将第三重循环变成一个从数组最右端开始向左移动的指针。(且需要满足
b ≤ c
)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
// 枚举 a
for (int first = 0; first < n; ++first) {
// 需要和上一次枚举的数不相同, 也是达到去重的效果
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first];
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同, 也是达到去重的效果
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧, 只有当三数之和大于 0, 才移动 c 的指针
while (second < third && nums[second] + nums[third] > target) {
--third;
}
// 随着 b 后续的增加, 指针可能会重合
// 则不满足 b < c 的条件了, 可以退出循环
if (second == third) {
break;
}
if (nums[second] + nums[third] == target) {
ans.push_back({nums[first], nums[second], nums[third]});
}
}
}
return ans;
}
};