题目描述
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
样例
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0。
不同的三元组是 [-1,0,1] 和 [-1,-1,2]。
注意,输出的顺序和三元组的顺序并不重要。
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0。
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0。
限制
3 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5
算法
(两重枚举,无重复构造) $O(n^2)$
- 延续算法 2 的思路,尝试不使用集合操作来判重。
- 同样是一重循环
st
无重复枚举第一个数字,然后接下来采用两头向里寻找的方式无重复的构造剩下的两个数字,具体在循环中:- 初始化
l
为st+1
,r
为n-1
。 - 当
l<r
时,如果当前nums[l] + nums[r] == target
,则增加答案并同时向后无重复移动l
,向前无重复移动r
;否则根据nums[l] + nums[r]
与target
的关系判断移动l
还是移动r
。
- 初始化
时间复杂度
- 排序的时间复杂度为 $O(n \log n)$。
- 第一层
for
循环执行 $n$ 次,每次内部会遍历st
后所有的数字一次,故时间复杂度为 $O(n^2)$。
空间复杂度
- 需要数组存储所有答案,故空间复杂度最高为 $O(n^2)$。
C++ 代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int st = 0; st < nums.size(); st++) {
while (st != 0 && st < nums.size() && nums[st] == nums[st - 1])
st++;
int l = st + 1, r = nums.size() - 1;
while (l < r) {
if (nums[st] + nums[l] + nums[r] == 0) {
res.push_back({nums[st], nums[l], nums[r]});
do { l++; }while (l < r && nums[l - 1] == nums[l]);
do { r--; }while (l < r && nums[r] == nums[r + 1]);
}
else if (nums[st] + nums[l] + nums[r] < 0) {
do { l++; }while (l < r && nums[l - 1] == nums[l]);
}
else {
do { r--; }while (l < r && nums[r] == nums[r + 1]);
}
}
}
return res;
}
};
请问 空间复杂度为什么是 O(n ^ 2) 呢
答案最多有 $O(n^2)$ 组吧
emmm 为什么呢
考虑一下暴力枚举,也是枚举两个数字,第三个数字就自动出来了
emm,可以的么?
在选定了第一个数之后,第二个数并不能任意选的,而且还不能包含重复元祖。所以答案永远不会有 O(n^2) 吧。我这里问的是空间复杂度。
最坏情况可以达到 $O(n^2)$ 的
时间复杂度都是看最坏情况的,没问题
为什么要定义两个vector呀?
?
这里是指vector[HTML_REMOVED]>吧,跟int a[][]一样,通过vector定义二维数组
思想非常巧妙, 和11题盛最多水的容器里的双指针用法很像
老哥能不能解释一下第一种方法那个vis的作用,还是没有看懂
简单来说是用来去重的
谢谢看懂了
为什么第一个方法我在leetcode里面跑会超时啊
第一个方法常数比较大,可能是以前数据比较水,现在加强了数据,可能过不了了
尝试了一下,第三个解答,要在第一个while循环&&一个st<n-1才能AC。。
啊,感谢修正,确实需要判断一下数组结尾。