leecode 18. 四数之和

18. 四数之和

         四数之和与前面三数之和的思路几乎是一样的,嗝。(刚好前些天才写了三数之和的题解)
如果前面的三数之和会做了的话,这里其实就是在前面的基础上多添加一个遍历的指针而已。会做三数之和的可以不用看下面的了。
         使用四个指针(a<b<c<d)。固定最小的a和b在左边,c=b+1,d=_size-1 移动两个指针包夹求解。保存使得nums[a]+nums[b]+nums[c]+nums[d]==target的解。偏大时d左移,偏小时c右移。c和d相遇时,表示以当前的a和b为最小值的解已经全部求得。b++,进入下一轮循环b循环,当b循环结束后, a++,进入下一轮a循环。 即(a在最外层循环,里面嵌套b循环,再嵌套双指针c,d包夹求解)。
链接:https://leetcode-cn.com/problems/4sum/solution/shuang-zhi-zhen-jie-fa-can-zhao-san-shu-zhi-he-ge-/
 

相当于在三数之和的基础上多加了一层遍历循环

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> q = new ArrayList<List<Integer>>();
        int len = nums.length;
        if (nums == null || len < 4) return q;
        // 排序
        Arrays.sort(nums);
        for (int i = 0; i < len - 3; i++) {
            // 去重
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            // 如果这四数之和大于target, 往后算也必大于target
            if ((long)nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
            // 下面这四数之和小于target, 则nums[i]小了
            if ((long)nums[i] + nums[len - 3] + nums[len - 2] + nums[len -1] < target)  continue;
            for (int j = i + 1; j < len - 2; j++) {
                // 去重
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                // 如果这四数之和大于target, 往后算也必大于target
                if ((long)nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
                // 如果这四数之和大于target, 往后算也必大于target
                if ((long)nums[i] + nums[j] + nums[len - 2] + nums[len - 1] < target) continue;
                // 接下来就是熟悉的双指针算法啦
                int L = j + 1;
                int R = len - 1;
                while (L < R) {
                    int sum = nums[i] + nums[j] + nums[L] + nums[R];
                    if (sum == target) {
                        q.add(Arrays.asList(nums[i], nums[j], 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 (sum < target) {
                        // 小了就往右移
                        L++;
                    } else {
                        // 大了就往左移
                        R--;
                    }
                }
            }
        }
        return q;
    }
}

第二天重新做了一遍,细节还是做不到位,下方代码。 

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        int len = nums.length;
//遍历到还有倒数第四个数结束。
        for (int i = 0; i < len - 3; i ++) {
            // 去重,在第二次遍历开始后判断是否和前一个数相等,相等就跳过这个位置。
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            // 如果这四数之和大于target, 终止,因为往后算也必大于target。
            if ((long)nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
            // 下面这四数之和小于target, 则nums[i]小了,跳过
            if ((long)nums[i] + nums[len - 3] + nums[len - 2] + nums[len -1] < target)
                 continue;
            for (int j = i + 1; j < len - 2; j ++) {
                // 去重,同上的去重
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                // 如果这四数之和大于target, 往后算也必大于target,同上
                if ((long)nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
                // 如果这四数之和大于target, 往后算也必大于target,同上
                if ((long)nums[i] + nums[j] + nums[len - 2] + nums[len - 1] < target) 
                    continue;
                int l = j + 1;
                int r = len - 1;
                while (l < r) {
                    if (nums[i] + nums[j] + nums[l] + nums[r] == target) {
                        res.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
                        //去重,用while判断不用if,防止有多个重复。
                        while (l < r && nums[l] == nums[l + 1]) l++;
                        while (l < r && nums[r] == nums[r - 1]) r--;
                        l++;
                        r--;
                        //这用else if 和else,刚开始我用的两个if判断,会少情况
                    }else if (nums[i] + nums[j] + nums[l] + nums[r] > target) {
                        r --;
                    }else {
                        l ++;
                    }
                }
            }
        }
        return res;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值