LeetCode15. 3Sum(对撞指针)
- Medium
- Accepted:473,172
- Submissions:2,039,197
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
链接
https://leetcode.com/problems/3sum/
题意
给定一个包含n个整数的数组,找到所有和为0的三元组(a, b, c | a + b + c = 0)。
题解
- 这题和LeetCode1. Two Sum(思维)的思路一样,也就是先两重循环得到nums[i]+nums[j],然后再查询-(nums[i]+nums[j])在不在数组内,但是难点就是不能含有同样的三元组(即两个三元组中的元素都相同),我们做的时候会出现不同的索引相同的值
-1 0 1 / 0 1 -1
,那怎么解决这个问题呢? - 实际上当确定了两个元素之后第三个元素也就唯一确定了,比如当
-1 0 1
确定时,其中任意两个元素不能在新的三元组出现,否则就会重复。 - 因此我们可以先对元素进行排序,然后一层循环找出一个值nums[i],再使用对撞指针的方法找另外两个元素nums[l]和nums[r]使得元素和为0,此时如果出现了元素值相等得情况就可以对指针进行右移或左移,因为已经确定了两个元素,这样就去除了可能的重复三元组。
- 时间复杂度$O(nlogn + n^2) = O(n^2)$
- 如果是返回不同索引的话,我们可以使用unordered_map加两层循环来做。
代码
- Runtime: 124 ms, faster than 80.33% of C++ online submissions for 3Sum.
- Memory Usage: 16.4 MB, less than 100.00% of C++ online submissions for 3Sum.
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> ans;
sort(nums.begin(), nums.end());
for (int i = 0; i < n - 2; ++i)
{
if (i > 0 && nums[i] == nums[i-1]) // 后面一个元素与前面一个元素相同时,找到的三元组一样
continue;
int l = i + 1, r = n - 1;
while (l < r)
{
int sum = nums[i] + nums[l] + nums[r];
if (sum > 0)
r--;
else if (sum < 0)
l++;
else // 找到
{
ans.push_back({nums[i], nums[l], nums[r]});
while (l < r && nums[l+1] == nums[l]) // 相同元素左指针右移
++l;
while (l < r && nums[r-1] == nums[r]) // 右指针左移
--r;
++l, --r;
}
}
}
return ans;
}
};
注意在对数组进行操作时,一定要防止下标溢出,所以需要在while循环中加上l < r
的限定条件,否则对于数据0 0 0
会产生溢出。
参考
The end.
2019年2月16日 星期六
界面很漂亮呀!
谢谢夸奖~