解体思路:需要三个数相加为0,则另外两个数相加应该为上述第一个数的相反数,我们可以利用双指针在剩余的子数组中找有没有这样的数对。
···双指针指向剩余子数组的首尾,如果二者相加为目标值,那么可以记录,而且二者中间的数字相加可能还会有 。
就让排好序的数组依次当tag:for(int i = 0; i < n - 2; i++){
。。跟哈希的关系在那里?用到了数组哈希去逐个查找元素求和判断等不等于tag?
详细注释
class Solution {
public:vector<vector<int> > threeSum(vector<int> &num) { //返回类型是n和装有符合题目的三元组
vector<vector<int> > res;
int n = num.size();
//不够三元组 fast-template
if(n < 3)
return res; //res为空 没加元素进去
//排序
sort(num.begin(), num.end()); //元素排序
for(int i = 0; i < n - 2; i++){ //假如5个数,n=2的时候下面已经在对 n=3,n=4操作了 否则就越界了
if(i != 0 && num[i] == num[i - 1]) //i=0是因为&后面要判断num【i-1】,就是从前往后的时候,如果后一个数和当前一样就不用再判断了,直接 continue;下一次循环,而且肯定不是第一次进循环
continue;
//后续的收尾双指针
int left = i + 1; //那么后一个数和前一个数不一样或者是第一次进循环,摆好对撞指针
int right = n - 1;
//设置当前数的负值为目标
int target = -num[i];
while(left < right){ //指针不相遇说明没遍历完,直到指针对撞
//双指针指向的二值相加为目标,则可以与num[i]组成0
if(num[left] + num[right] == target){ //如果找到目标。开始去重 eg:0,-1-1-1 -2 0 0 0 0 1 1 2 2 2 目标是0找到1和-1一致去重 ,这只是一趟,一趟可能好几个解0-11,0-22针对tag=0的一趟
res.push_back({num[i], num[left], num[right]});//加入-1 1
while(left + 1 < right && num[left] == num[left + 1]) //左右分别去重
//去重
left++;
while(right - 1 > left && num[right] == num[right - 1])
//去重
right--;
//双指针向中间收缩 去重后指针新位置开始,left指向-2 right指向0 ,找这一轮的第二个解0-22
left++;
right--;
}
//双指针指向的二值相加大于目标,说明太大了,要变小一点,所以右指针向左 ,注意:右指针只能向左走,左指针只能向右走
else if(num[left] + num[right] > target)
right--;
//双指针指向的二值相加小于目标,左指针向右
else left++;
}
}
return res; }
};