20210414力扣第15题:三数之和

1.题目

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例1
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
 
示例2
输入:nums = []
输出:[]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum


2.自己想法及代码

自己的想法比较简单,就遍历每一个数字,用三个for循环,当数字和加起来是0的时候,就把他们放入list中,自己写完并提交后,发现会重复,再解决重复的问题,写好后,不得不说,三个for循环 一定会超时了,那只好看一下别人的思路了,自己的思路代码如下:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        if(nums.length==0||nums==null) 
        {
            List<List<Integer>> lll = new ArrayList<>();
            return lll;
        }
        
        HashSet h = new HashSet();//为了解决重复问题,使用hashset
        int length = nums.length;
      
        for(int i =0;i<length;i++)
        {
            for(int j = i+1 ;j<length;j++ )
            {
                for(int k = j+1;k<length;k++)
                {
                    if(nums[i]+nums[j]+nums[k] == 0)
                    {
                      
                        List<Integer> li = new ArrayList<>();
                        li.add(nums[i]);
                        li.add(nums[j]);
                        li.add(nums[k]);
                        Collections.sort(li);//从小到大的排序 这里是需要排序的 
                        //要不然[-1,0,1]和[1,-1,0]这两个数组是不相等的,
                        //即使hashset也不能识别出来,这样最后输出就回有问题

                        h.add(li);
                        
                    }
                }
            }
        }
        List<List<Integer>> lll = new ArrayList<>(h);
        return lll;
    
   
    }
}

这样可以完成简单的三数之和,但是测试用例 很多个数字就不能完成了,那就需要进一步改进了。

3.看别人的想法及代码

想法:

  1. 将nums排序,这样就变成了从小到大的顺序了
  2. 从小到大,使用一个双指针,一个在左,一个在右,遍历数组i,那么nums[i]+nums[L]+nums[R]=0
  3. 去重问题,重新排序的数组 ,两两之间 相等的就略过,不再比较了。
  4. 在内循环中 始终 L<R, sum=0就加入到list中,并且继续移动L和R,要不然出不了这个while循环。
  5. 最后返回;

写一下看看吧:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

    //排序
    Arrays.sort(nums);//从小到大了
    List<List<Integer>> res = new ArrayList();
    int len = nums.length;
    //开始遍历
    for(int i = 0 ; i < len ; i++)
    {
        if(nums[i] >0 ) break;//说明这个数最小值大于0了
        if(i>0&&nums[i] == nums[i-1]) continue;//重复的就不要了
        int l = i+1;//这个l不是从0 开始 从0 开始就会出现重复元素了
        int r = len -1;
        while(l<r)
         {
               int sum = nums[i]+nums[l]+nums[r];
                if(sum == 0)
                {
                    //将这三个元素加入到res中
                    res.add(Arrays.asList(nums[i],nums[l],nums[r]));
                    //有重复元素就去除掉
                    while(l<r && nums[l] == nums[l+1]) l++;
                    while(l<r && nums[r] == nums[r-1]) r--;
                    //去除完了 继续自加  自减
                    l++;
                    r--;
                 }
                //要记住 还要写else 否则 if语句不成立的话 while跳出不了循环  时间超时
                else if(sum <0) l++;
                else if(sum > 0) r--;
          }
    }
    return res;


    }
}

其中需要注意的点在于:

  1. 虽说是双指针,但左边的指针是从i+1开始的,不能搞错了
  2. Arrays.asList() 括号中的元素也要从小到大开始,否则输出的时候结果就元素大小顺序有问题。
  3. if(sum==0)和两个else不能 不写,否则while不能出循环。

4.总结

 看到这样的题就想着用循环,循环可以解决,但是一般只能使用两个循环,当使用三个时候,绝大部分都会超时,以后要注意这点,用一个for循环,用一个双指针,避免出现三个循环,三个循环解决实际问题并好;

还有,在三个循环的时候,解决重复问题犯了愁,没想到可以使用排序的方式从小到大,在加一个hashset,这样就可解决重复问题;

还没有熟练掌握Arrays的方法,写的时候可能会少写S,这次用到的方法有Arrays.sort和Arrays.asList();还有Collections.sort是对List排序,Arrays是对数组排序;

自己虽然看了第二个方法的思路,按照他的思路去写,但是没有理解的透彻,所以写着写着就想去看一下答案,看看哪里有问题,比如l和r的定义在for循环内,只写了if没有写else 不能跳出for循环。还有hashset中也用的是add方法添加,对此不熟还百度了。最近做题遇到了双指针较多,以后需要循环的时候也要考虑到。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值