三数之和,点击左侧即可跳转。
目录
- 题目详情:
- 思路:
- 暴力:
- 双指针:
- 代码实现:
题目详情:
思路:
暴力:
我们会显而易见的想到使用暴力解法,3个for循环暴力枚举再进行check即可,大思路很简单就可以想到
但是这题的细节很多,我们注意到题明确说明不能有重复的三元组,这对于平时做题时可以直接使用set容器去重,但是前提是我们要有序,那么我们就要再先排序再进行for循环的3个嵌套。
但是暴力循环是效率很低的,我们便不再实现这种代码。
双指针:
我们在遇到有单调性的数组时要及时的想到双指针这种优秀的算法,一般可以直接将时间复杂度降一维。
那么该如何使用双指针呢?
我们可以先思考一下如何求两数之和
这题可以使用双指针就可以很高效的解答。
知道两数之和的解法那么三数之和也就自然而然的想到了
- 将数组排序
- 从左到右依次固定住一个元素
- 在其右侧区间进行查找
注意:
- 但是这题使用set容器去重是很方便的,
但如果面试的时候肯定要手搓一个去重 - 另外由于我们两数之和是返回一对正确答案即可停止,但是这题我们找到一对后要继续,防止遗漏。、
代码实现:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> vv;
for (int i = 0; i < nums.size() - 2; i++)
{
//去重i
if(nums[i] > 0) break;
while (i > 0 && i < nums.size() - 2 && nums[i] == nums[i - 1])
i++;
int left = i + 1, right = nums.size() - 1;
while (left < right)
{
if ((-nums[i]) == (nums[left] + nums[right]))
{
vector<int> v;
v.push_back(nums[i]);
v.push_back(nums[left]);
v.push_back(nums[right]);
vv.push_back(v);
//防漏
left++;
while (left < right && nums[left] == nums[left - 1])
left++;
//防漏
right--;
while (left < right && nums[right] == nums[right + 1])
right--;
}
else if ((-nums[i]) < (nums[left] + nums[right]))
{
//去重
right--;
while (left < right && nums[right] == nums[right + 1])
right--;
}
else
{
//去重
left++;
while (left < right && nums[left] == nums[left - 1])
left++;
}
}
}
return vv;
}
};