题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
样例
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
算法思路
双指针法
因为没有三指针算法,所以为了处理三个数的和的问题,我们需要先固定一个元素,然后对剩下的数进行双指针算法。双指针算法的应用前提是要求数组的元素有序,所以需要对原数组进行排序。同时为了避免答案重复,在枚举过程中需要跳过相同元素。为了提高一点时间,可以做一点小优化,类似于最小的三个数之和都大于0或最大的三个数之和都小于0时,可以跳过直接进行下一次枚举。
C++ 代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if (nums.size() < 3) return res; //没有三个元素
sort(nums.begin(), nums.end()); //排序
for (int i = 0; i < nums.size() - 2; i ++) //枚举第一个数并固定
{
int j = i + 1, k = nums.size() - 1; //剩下元素进行双指针
if (i && nums[i] == nums[i - 1]) continue; //跳过重复的i
if (nums[i] + nums[i + 1] + nums[i + 2] > 0) break; //最小的三个数都大于0了,所以跳过
if (nums[i] + nums[k - 1] + nums[k] < 0) continue; //最大的三个数都小于0了,所以跳过
while (j < k) //双指针
{
int s = nums[i] + nums[j] + nums[k];
if (s > 0)
{
k --;
while (j < k && nums[k] == nums[k + 1]) k --; //跳过相同的k
}
else if (s < 0)
{
j ++;
while (j < k && nums[j] == nums[j - 1]) j ++; //跳过相同的j
}
else
{
res.push_back({nums[i], nums[j], nums[k]}); //加入答案
j ++, k --;
while (j < k && nums[k] == nums[k + 1]) k --; //跳过相同的k
while (j < k && nums[j] == nums[j - 1]) j ++; //跳过相同的j
}
}
}
return res;
}
};