Leetcode 15. 三数之和
题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
思路
-
哈希解法
通过两层for循环确定a +b 的数值,可以使用哈希法来确定0- (a + b)是否在数组里面出现过,注意去重 -
双指针法
- 首先将数组进行排序
- i从下标0的位置开始,同时定一个下标left在i + 1的位置,定义下标right在数组结尾上
- 如果nums[i] + nums[left] + nums[right] > 0 就说明三数之和大于0,right–
- 如果nums[i] + nums[left] + nums[right] < 0 就说明三数之和小于0,left++
- 直到 等于0为止,并且找到一个三元组之后 需要进行去重
代码
- 哈希法
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;// 存储三元组
sort(nums.begin(),nums.end());// 数组进行排序
// 使用哈希数组的方法 两层for循环就可以确定a和b的数值 然后使用哈希数组判断 0 - (a + b)是否在数组中出现过
// a = nums[i] b = nums[j] c = 0 - (a + b)
for(int i = 0; i < nums.size(); i++)
{
if(nums[i] > 0)
{
break;// 排序之后如果第一个元素大于0 那么就不可能凑成三元组
}
// 三元组元素a去重
if(i > 0 && nums[i] == nums[i - 1])
{
continue;// 说明当前nums[i]元素前面已经出现过 直接pass 计算nums[i + 1]
}
unordered_set<int> set;// 定义一个哈希数组
// 查看b
for(int j = i + 1; j < nums.size(); j++)
{
//
if(j > i + 2 && nums[j] == nums[j - 1] && nums[j - 1] == nums[j - 2])
{
// 三元组元素b去重
continue;
}
int c = 0 - (nums[i] + nums[j]);// 查找c是否在哈希数组中
if(set.find(c) != set.end())
{
result.push_back({nums[i],nums[j],c});
set.erase(c);// 三元组元素c去重
}
else
{
set.insert(nums[j]);// 没有查找到 将其插入set
}
}
}
return result;
}
};
- 双指针法
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(),nums.end());
// a = nums[i] b = nums[left] c = nums[right]
for(int i = 0; i < nums.size(); i++)
{
// 如果第一个元素大于0 那么不可能凑成三元组
if(nums[i] > 0)
{
return result;
}
// 去重
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{
// 找到一个三元组
result.push_back(vector<int>{nums[i],nums[left],nums[right]});
// 去重
// 判断right--元素 也就是nums[right] == nums[right- 1] 是否相等 相等的话 直接pass
while(right > left && nums[right] == nums[right - 1])
{
right--;
}
while(right > left && nums[left] == nums[left + 1])
{
left++;
}
// 找到答案 同时进行收缩
right--;
left++;
}
}
}
return result;
}
};