力扣:l15. 三数之和 - 力扣(LeetCode)
参考的视频力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
还是贴一下代码:
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(),nums.end());int n=nums.size();vector<vector<int>> ans;for(int i=0;i<n-2;i++){int x=nums[i];if(x+nums[i+1]+nums[i+2]>0)break;if(x+nums[n-1]+nums[n-2]<0)continue;if(i>0&&nums[i-1]==x)continue;int j=i+1,k=n-1;while(j<k){if(x+nums[j]+nums[k]>0)k--;else if(x+nums[j]+nums[k]<0)j++;else{ans.push_back(vector<int>{x,nums[j],nums[k]});j++;while(j<k&&nums[j]==nums[j-1]) j+=1;k--; while(j<k&&nums[k]==nums[k+1])k-=1;}}}return ans;}
};
1.太久没用vector的东西,排序方法都不知道怎么调用了。
末尾添加元素用push_back()。
发现vector内部没有直接调用的方法,而是有一个模板函数sort(并且要包含头文件#include <algorithm>):C++中使用sort对常见容器排序_c++ vector sort-CSDN博客
2.三数之和是枚举第一个数,剩下两个数按双指针处理两数之和的方法来处理,所以需要对数组进行一次排序。
3.题目强调了“注意:答案中不可以包含重复的三元组。”,所以需要有去除重复的操作,因为经过了排序,所以在枚举第一个数和处理两数之和移动双指针时,只要出现和前面一个数相同的元素就跳过,因为三元组不重复,所以这个重复的数的组合肯定已经全部找到,剩下的两数之和找到的二个数,如果一个数还是相同的,另一个数肯定也就确定最多只能找到相同的。
4.在移动指针时,要注意判断下标越界,并且要把判断条件写在&&的前面,因为&&前面的条件先判断,如果不成立后面的条件判断不会执行。
if (i > 0&& x == nums[i - 1] ) continue;
这一句要把i>0放在&&前面,避免出现下标为负的情况。
同理,双指针移动还要注意两个指针的大小(左右)关系的成立,比如
while(j<k&&nums[j]==nums[j-1]) j+=1;
不只是外部的while(j<k)要执行这个判断,在求两数之和去除重复的组合时移动指针时也要有这个判断,并且j<k也要放在&&的前面。
如果写在后面会出现这个错误提示:
Line 1037: Char 34: runtime error: addition of unsigned offset to 0x502000000290 overflowed to 0x50200000028c (stl_vector.h)
5.两个优化:
if(x+nums[i+1]+nums[i+2]>0) break;
if(x+nums[n-1]+nums[n-2]<0) continue;
第一个优化是如果目前最小的三个数加起来都大于0,那么剩下的组合肯定都大于0(排除了重复就只有大于0),另外这个已经包括了if(nums[i] > 0) break;的判断。
第二个优化是枚举的第一个数和剩下的两个最大的数加起来都小于0,那么不可能出现包括这个第一个数的三元组合等于0,所以跳过这轮枚举。注意是跳过这轮,continue,因为下一个数的枚举再组合是有可能大于等于0的。