leecode15——三数之和

leecode中有两数之和 三数之和 四数之和等

两数之和可利用hashmap快速求解

三数之和 若转化为两数组之和做 反正我是没解出来

前天晚上 还提醒自己 如果需要多个循环  可借用双指针或者从后开始处理

今天就没想到~!!!!!!!

错误解法1——暴力解法

HashMap hash=new HashMap();
        List<List<Integer>> list=new LinkedList<>();
        List<Integer> list2;
        for(int i=0;i<nums.length;i++){
            tar=-1*nums[i];
            for(int j=0;j<nums.length;i++){
                if(j==i){
                    continue;
                }else{
                    if(hash.containsKey(nums[j])){
                        list2=new LinkedList<>();
                        list2.add(nums[i]);
                        list2.add(nums[j]);
                        list2.add(tar-nums[j]);
                        //hash.put(nums[j],tar-nums[j]);//这里面一组就是其中一对  再求反便可
                        list.add(list2);
                    }
                    hash.put(tar-nums[j],nums[j]);
                }
            }
        }

错误解法2——每个数组只考虑一次情况,即在双指针的情况下,只遍历一次

         while(left<right){//这样  每组只有一组符合的数据 因为只循环一次。
                if((nums[left]+nums[right])<tem){
                    ++left;
                }else if((nums[left]+nums[right])>tem){
                    --right;
                }else{
                    list2=new LinkedList<>();
                    list2.add(-1*tem);
                    list2.add(nums[left]);
                    list2.add(nums[right]);
                    list.add(list2);
                    left=((left+1)==nums.length-1)?++left:--right;
                }
            }

正解

public List<List<Integer>> threeSum(int[] nums) {
        //之前有遇到过四数之和 无解
        //类似的哈希表算法:242 1002 349 202 1 454 383 15 18

        //三数之和转化为  两数之和问题?
        //三数之和 中加入双指针解决

        //升序
        Arrays.sort(nums);
        LinkedList<List<Integer>> list=new LinkedList();
        if(nums==null||nums.length<2) return list;
        if(nums[0]>0) return list;
        

        List<Integer> list2;
        int tem=0;
        int left=0;
        int right=0;
        int sum=0;
        for(int i=0;i<nums.length;i++){
            tem=nums[i];
            if(i>=1){
                if(nums[i]==nums[i-1]) continue;
            }
            left=i+1;
            right=nums.length-1;
             while (left<right){
                sum=tem+nums[left]+nums[right];
                if (sum==0){
                    list2=new LinkedList<>();
                    list2.add(tem);
                    list2.add(nums[left]);
                    list2.add(nums[right]);
                    list.add(list2);
                    while (left<right&&nums[left]==nums[left+1]) ++left;//这里是去重   也是最难的一部分
                    while (left<right&&nums[right]==nums[right-1]) --right;
                    ++left;//这里才是关键   上面确实去重 往后走了一步  但是 数值并没变 所以要继续走一步 即总共走两步
                    --right;
                }else if(sum<0) ++left;
                else if(sum>0) --right;
            }
            
        }
        return list;
    }

核心在于这两步

在while中,sum是三数之和,

若sum不等于0,那么进行左右移动

如果sum==0 存完之后,判断一下left的右边一位,和right的左边一位是否相等;

01如果相等,那么跳到该步,而下面两个while循环,会进一步靠中间一步,一来彻底不走重复  (A,A,B——sum==0时,在A,判断之后右一位相等,则while继续走到B)

当然也会想到如果是(A,X,A)的情况 left是A,right也是A,那么两个小while之后 left和right都是X了,注意!:A+A+tem=0,如果X==A那么中间那步不要也行,因为前任保存了,如果X!=A,那么X+X+tem肯定不为0,所以最后也不走!

直呼巧妙

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值