给你一个整数数组 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,1,1] 输出:[]
三.解题分析示例三:
输入:nums = [0,0,0] 输出:[[0,0,0]]
本题采用排序和双指针的解法:
题目中指出需要寻找三个不同的并且和为0的三元组,所以我们需要用到三个循环并且每次遍历的元素都要比前一次遍历少一个元素。因为第一次遍历以第一个数为基点,去寻找第二个元素,然后确定好前两个元素后再去寻找第三个元素,另外两个需在除第一次遍历确定的元素以外剩下的数组中找出才不算有重复元素(第二次遍历同理)。此时需要用到三个循环来确定三个元素才得以完成,时间复杂度为 ,那么我们应该怎么减小时间复杂度呢?
减少时间复杂度可以通过减少循环来解决,由上面知需要一个一个的寻找元素来确定是否其和为0,减少时间复杂度就需要减少寻找一个元素的循环,那我们就可以定一变二。
例:当确定第一个元素时n1时,另外两个元素n2和n3和就为-n1;即为一个不变值;当n2增大时n3减小,当n2减小时n3增大
这样我们就可以 在确定第一个元素后,运用双指针来同时确定第二个和第三个元素的值。因为需要判断增大减小,就必须先给数组排序运用sort即可。
基本步骤:
1.将数组由小到大排序
2.利用for循环枚举第一个元素
3.确定第三个元素指针位置
4.枚举第二个元素并寻找是否存在第三个元素满足条件
每一步都需要判断两数之和是大于-n1还是小于-n1,若大于则移动第三个元素指针,若小于则移动第二个元素指针;当两个指针相等时则代表无解。
5.将三个元素存入三元组并返回 vector
>
以[2,5,3,-5,-1,4]数组为例演示双指针移动过程,排序好的数组如下图:
橙色区域为确定好的第一个元素,紫色指针指向第二个元素,红色指针指向第三个元素
这样我们可以清楚的了解双指针移动的判断条件对应的移动位置了。
万事俱备,只欠东风!让我为大家讲解(注:仅为讲解代码,帮助家人们理解)一下代码吧!
class Solution {
public:
vector>threeSum(vector& nums) {
sort(nums.begin(),nums.end());//先给代码排序
int n=nums.size();//用n来代替数组的大小
vector>sum;//创建一个数组,用来存放三元组
//枚举第一个元素,第一层循环需要全部遍历
for(int i=0;i0&&nums[i]==nums[i-1]) continue;
//确定第三个元素指针
int c=n-1;
int target=-nums[i];//后两个元素和
//枚举第二个元素
for(int b=i+1;bi+1&&nums[b]==nums[b-1]) continue;
//判断指针移动条件
while(btarget){
c--;
}
if(b==c)break;//若两个指针相等了还无解,就不用再比下去了
//如果三个元素和为0,则加入三元组中
if(nums[b]+nums[c]==target){
sum.push_back({nums[i],nums[b],nums[c]});
}
}
}
return sum;//输出三元组
}
};
当我们需要确定多个元素时,若要减小时间复杂度则可以采用指针的方法同时进行操作不需要嵌套。好啦,这道题就讲解完成了,以后我也会多多更新的,欢迎大家持续关注我哟!
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧