题目描述
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入: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] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解思路
采用 排序+双指针
算法流程:
特判,对于数组长度 nnn,如果数组为 nullnullnull 或者数组长度小于 333,返回 [][][]。
对数组进行排序。
遍历排序后数组:
若 nums[i]>0nums[i]>0nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 000,直接返回结果。
对于重复元素:跳过,避免出现重复解
令左指针 L=i+1L=i+1L=i+1,右指针 R=n−1R=n-1R=n−1,当 L<RL<RL<R 时,执行循环:
当 nums[i]+nums[L]+nums[R]==0nums[i]+nums[L]+nums[R]==0nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,RL,RL,R 移到下一位置,寻找新的解
若和大于 000,说明 nums[R]nums[R]nums[R] 太大,RRR 左移
若和小于 000,说明 nums[L]nums[L]nums[L] 太小,LLL 右移
复杂度分析
时间复杂度:O(n2)O\left(n^{2}\right)O(n2),数组排序 O(NlogN)O(N \log N)O(NlogN),遍历数组 O(n)O\left(n\right)O(n),双指针遍历 O(n)O\left(n\right)O(n),总体 O(NlogN)+O(n)∗O(n)O(N \log N)+O\left(n\right)*O\left(n\right)O(NlogN)+O(n)∗O(n),O(n2)O\left(n^{2}\right)O(n2)
空间复杂度:O(1)O(1)O(1)
作者:wu_yan_zu
链接:https://leetcode.cn/problems/3sum/solution/pai-xu-shuang-zhi-zhen-zhu-xing-jie-shi-python3-by/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
程序代码 c++
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(),nums.end());
int n=nums.size();
int left,right;
for(int i=0;i<n-2;i++){
if(nums[i]>0)
return res;
if(i>0&&nums[i]==nums[i-1])
continue;
left=i+1;
right=n-1;
while(left<right){
if(nums[i]+nums[left]+nums[right]==0){
res.push_back({nums[i],nums[left],nums[right]});
while(left<right&&nums[left]==nums[left+1])
left++;
while(left<right&&nums[right]==nums[right-1])
right--;
// 找到答案时,双指针同时收缩
right--;
left++;
}else if(nums[i]+nums[left]+nums[right]>0){
right--;
}else{
left++;
}
}
}
return res;
}
};
参见视频: