LeetCode - 4Sum

题目

  输入一个数组和一个目标值,返回所有的4个数的和等于目标值的组合。

思路

  这个问题是 TwoSum3Sum 的变种,和3Sum一样,先确定一个值,然后从剩下的数组中找一个3Sum的结果,再把当前值加入,逐次遍历即可。

代码

public List<List<Integer> > fourSum(int[] nums, int target) {
    List<List<Integer> > res = new ArrayList<>();
    if (nums == null || nums.length < 4) {
        return res;
    }
    // 先排序
    Arrays.sort(nums);
    // 剔除极端情况
    if (nums[0] * 4 > target || nums[nums.length - 1] * 4 < target) {
        return res;
    }
    for (int i = 0 ; i < nums.length ; ) {
        int[] tmp = new int[nums.length - 1 - i];
        System.arraycopy(nums, i+1, tmp, 0, tmp.length);
        List<List<Integer>> current = threeSum(tmp, target - nums[i]);
        for (List<Integer> list : current) {
            list.add(0, nums[i]);
            res.add(list);
        }

        int num = nums[i];
        while (i < nums.length && nums[i] == num) {
            i++;
        }
    }
    return res;
}

private List<List<Integer>> threeSum(int[] nums, int target) {
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    if (nums == null || nums.length < 3) {
        return res;
    }
    // 输入数组是已经排序过的
    // Collections.sort(list);
    int tmpTarget = 0;
    for (int i = 0 ; i < nums.length - 2 ;) {
        // 目标值,转化为TwoSum问题
        tmpTarget = target - nums[i];
        // 从i后一个结点开始查找
        int left = i + 1;
        int right = nums.length - 1;
        while (left < right) {
            int tmp = nums[left] + nums[right];
            // 找到了一对
            if (tmp == tmpTarget) {
                ArrayList<Integer> tmpList = new ArrayList<>();
                tmpList.add(nums[i]);
                tmpList.add(nums[left]);
                tmpList.add(nums[right]);
                res.add(tmpList);
                // 跳过重复的
                int num = nums[left];
                while (num == nums[left] && left < right) {
                    left++;
                }
            } else if (tmp < tmpTarget) {
                int num = nums[left];
                while (num == nums[left] && left < right) {
                    left++;
                }
            } else {
                int num = nums[right];
                while (num == nums[right] && right > left) {
                    right--;
                }
            }
        }
        // 跳过重复的
        int num = nums[i];
        // 注意判断顺序,如果颠倒了会抛出异常,应该先判断是否越界
        while (i < nums.length && nums[i] == num) {
            i++;
        }
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值