力扣算法题三数之和
15.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,
使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
这道算法题我苦思冥想了很久,始终不得解,看了题解才豁然开朗,感叹自己还是个算法小白。
此算法主要运用到的思想是排序+双指针,但是如何去重才是关键。
排序是为了能使用双指针,对于双指针,我本来是用for循环重新遍历一遍的,但是其实不然,使用while(L<R)去循环会很好的防止指针越界,也不用多做条件去判断。
思路
标签:数组遍历
首先对数组进行排序,排序后固定一个数 nums[i]nums[i]nums[i],再使用左右指针指向 nums[i]nums[i]nums[i]后面的两端,数字分别为 nums[L]nums[L]nums[L] 和 nums[R]nums[R]nums[R],计算三个数的和 sumsumsum 判断是否满足为 000,满足则添加进结果集
如果 nums[i]nums[i]nums[i]大于 000,则三数之和必然无法等于 000,结束循环
如果 nums[i]nums[i]nums[i] == nums[i−1]nums[i-1]nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
当 sumsumsum == 000 时,nums[L]nums[L]nums[L] == nums[L+1]nums[L+1]nums[L+1] 则会导致结果重复,应该跳过,L++L++L++
当 sumsumsum == 000 时,nums[R]nums[R]nums[R] == nums[R−1]nums[R-1]nums[R−1] 则会导致结果重复,应该跳过,R−−R--R−−
时间复杂度:O(n2)O(n^2)O(n2),nnn 为数组长度
以下是我的烂代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> zeronums = new ArrayList<>();
if(nums.length<3||nums==null){
return zeronums;
}
//排序
Arrays.sort(nums); // 排序
int leftp,rightp;
for (int i=0;i<nums.length;i++) {
leftp = i+1;
rightp = nums.length-1;
if(nums[i]>0){
break;
}
if(i>0&&nums[i]==nums[i-1]){
continue;
}
while (leftp<rightp){
//for (int j=0;j<nums.length-i-1;j++) {
int sum = nums[leftp]+nums[rightp]+nums[i];
if(sum==0){
List<Integer> zeronum = new ArrayList<>();
zeronum.add(nums[i]);
zeronum.add(nums[leftp]);
zeronum.add(nums[rightp]);
zeronums.add(zeronum);
//去重
while (leftp<rightp && nums[leftp] == nums[leftp+1]) leftp++;
while (leftp<rightp && nums[rightp] == nums[rightp-1]) rightp--;
leftp++;
rightp--;
}
if(sum>0){
rightp--;
}else if (sum<0){
leftp++;
}
}
}
return zeronums;
}
}
题解思路来自
作者:guanpengchn
链接:https://leetcode-cn.com/problems/3sum/solution/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。