day 7
又惨绝人寰!呵呵,不过下次遇到我一定可以的。
思路
1. 哈希法
这里是三个数组,我一开始想的思路没啥大问题。就是先算两个数的和,但注意,这里不需要将和存到集合中,因为这是在同一个数组中进行操作的。这里的去重比较麻烦。就不再写哈希法了。
哈希法的思路是ok的
2.双指针
一开始完全想不到双指针可以这样用。因为这里是求,三个数相加。两个指针怎样处理三个数?
这里就是巧妙用了一个for循环,来代替一个指针,主要需要移动的是循环内的指针。
去重主要是:不能出现[ 1,2,-3] [ 1,2,-3] ,向这样连续出现两次。
想清楚为什么去重是当 num[right] = num[right - 1] / num[ left ] = num[left + 1]
因为在一次循环中 ,num[i] 的值是固定的,如果num[right -1 ]或者 num[ left -1 ] 其中任意一个和上一次一样,那么另一个值也固定下来和上次一样了。这样就重复了。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
// 双指针 卡住的点:没想到可以用循环,作为一个可以自己移动的指针。
// 首先对数组进行排序
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size() ; i++)
{
// 可以先剪枝
if(nums[i] > 0) return res;
// 对 i 进行去重
if( i > 0 && nums[i] == nums[i - 1])
continue;
int left = i + 1;
int right = nums.size() - 1;
while(left < right)
{
if(nums[i] + nums[left] + nums[right] > 0)
right--;
else if(nums[i] + nums[left] + nums[right] < 0 )
left++;
else
{
res.push_back(vector<int>{nums[i], nums[left], nums[right]});
// 插入之后再对之后的去重,注意限定:right > left
while(right > left &&nums[right] == nums[right - 1])
right--;
while(right > left &&nums[left] == nums[left + 1])
left++;
// 去完重,也就是相当于收集完结果集
right--;
left++;
}
}
}
return res;
}
};