「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
15. 三数之和
题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c , 使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例 1:
输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
示例 2:
输入: nums = []
输出: []
示例 3:
输入: nums = [0]
输出: []
思路
a+b+c = 0 , 使用两层for循环可以记录 a和b ,再用哈希法 确定 c = 0 - (a+b)的值是否在数组中出现过。也可以使用双指针法来解决。
哈希法
class Solution
{
vector<vector<int>> threeSum(vector<int> &nums)
{
vector<vector<int>> ret;
sort(nums.begin(), nums.end());
// 找出三个数 a,b,c使得 a+b+c = 0
// 令 a = nums[i] , b = nums[j] , c = -(a+b)
for (int i = 0; i < nums.size(); i++)
{
// 排序后,如果第一个元素值大于0就无法构成三元组
if (nums[i] > 0)
{
continue;
}
// 三元组中元素a去重
if (i > 0 && nums[i] == nums[i - 1])
{
continue;
}
unordered_set<int> set;
for (int j = i + 1; j < nums.size(); j++)
{
// 三元组中元素b去重
if (j > i + 2 && nums[j] == nums[j - 1] && nums[j - 1] == nums[j - 2])
{
continue;
}
int c = 0 - (nums[i] + nums[j]);
if (set.find(c) != set.end())
{
ret.push_back({nums[i], nums[j], c});
// 三元组中元素c去重
set.erase(c);
}
else
{
set.insert(nums[j]);
}
}
}
return ret;
}
};
双指针
class Solution
{
// 双指针法
vector<vector<int>> threeSum(vector<int> &nums)
{
vector<vector<int>> ret;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++)
{
// 排序后,若第一个元素值大于0,则无法构成三元组
// 返回结果数组
if (nums[i] > 0)
{
return ret;
}
// 第一个数与相邻的元素相同时去重
if (i > 0 && nums[i] == nums[i - 1])
{
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while (left < right)
{
// 三数之和大于 0 ,右指针左移
if (nums[i] + nums[left] + nums[right] > 0)
{
right--;
}
// 三数之和小于 0 ,左指针右移
else if (nums[i] + nums[left] + nums[right] < 0)
{
left++;
}
else
{
// 三数之和等于0
ret.push_back({nums[i], nums[left], nums[right]});
// 此时,在进行去重操作
// 去重操作,过滤掉相邻且相等的元素
// 去重逻辑应该放在找到一个三元组之后
while (right > left && nums[right] == nums[right - 1])
{
// 去除右指针相同的元素
right--;
}
while (right > left && nums[left] == nums[left + 1])
{
// 去除左指针相同的元素
left++;
}
right--;
left++;
}
}
}
return ret;
}
};