思路
挑选三元组
- 将数据按从小到大排序
- 使用双指针,for循环的i从0开始,第一个指针为左指针,指向i+1;第二个指针为右指针,从数组的最右端开始
- 如果三数之和大于1,则右指针左移
- 如果三数之和小于1,则左指针右移
注意要点:答案中不能出现重复的三元组,意味着要去重
去掉重复的三元组
去掉移动i时的重复三元组
如果用以下的去重公式,则会把第一次出现且只出现一次的三元组答案去掉
if (nums[i] == nums[i+1])
所以应该使用以下公式,其中i>0是为了保证i-1不溢出
if (i > 0 && nums[i] == nums[i-1])
去掉移动双指针时的重复三元组
当指针移动,要去掉重复的元素
while (right > left && nums[left] == nums[left+1]) left++;
while (right > left && nums[right] == nums[right-1]) right–;
代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
// 循环移动i
for (int i = 0; i < nums.size(); i++)
{
// 如果第i个元素大于0,直接返回
if (nums[i] > 0)
return result;
// 去掉移动i时的重复三元组
if (i > 0 && nums[i] == nums[i-1])
continue;
// 定义双指针
int left = i + 1;
int right = nums.size() - 1;
// 固定i,移动双指针找答案
while (left < right)
{
if (nums[i] + nums[left] + nums[right] > 0)
right--;
else if (nums[i] + nums[left] + nums[right] < 0)
left++;
else
{
// 找到正确答案,放入结果中
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
// 出现重复元素,用while循环去掉
while (left < right && nums[left] == nums[left+1]) left++;
while (left < right && nums[right] == nums[right-1]) right--;
// 找到答案后,双指针同时移动
right--;
left++;
}
}
}
return result;
}
};