每天一题LeetCode[第十六天]

每天一题LeetCode[第十六天]


4 Sum

Description:
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

翻译:

给一串整型字符串数字,判断是否有这样的元素a b c d 满足 a+b+c+d=target? 给出target,找到所有满足条件的组合。
注意:组合必须没有重复。例子如上

解题过程:
  • 这道题是在3 Sum的基础上,又增加了一个变量。 思路很简单,就是如何把4 sum->变成3 sum 就可以解决啦。 如何转换呢,就是先排序一下,然后遍历,每次去一个作为基础值 x,就可以把4变成3,target变成 target-基础值。

  • 值得注意的是,一些细节,比如如果当前值 乘4小于target,那么 循环可以不用继续下去,还有很多,可以提高效率的判断,这方面做得没有top solution好。。还有一点是,记得要去重!!!参考Top Solution


Java代码:**
public class Solution {

    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        //如果为null或者长度还没到4
        if (null == nums || nums.length < 4) {
            return ans;
        }
        Arrays.sort(nums);
        //如果最小都大于target  或者 最大都小于target 则直接返回
        if (4 * nums[0] > target || 4 * nums[nums.length - 1] < target) {
            return ans;
        }


        for (int i = 0; i < nums.length - 3; i++) {
            int x = nums[i];
            if (i > 0 && x == nums[i - 1]) {
                continue;
            }
            //全部太大
            if (4 * x > target) {
                break;
            }


            //此次太小
            if (x + 3 * nums[nums.length - 1] < target) {
                continue;
            }

            if (4 * x == target && x == nums[i + 3]) {
                ans.add(Arrays.asList(x, x, x, x));
                i = i + 2;
                continue;
            }

            threeSum(ans, target - x, nums, i + 1, nums.length, x);

        }

        return ans;
    }

    private void threeSum(List<List<Integer>> ans, int target, int[] nums, int start, int end, int x) {
        if (start + 1 >= end) {
            return;
        }

        if (3 * nums[start] > target || 3*nums[end]<target) {
            return;
        }

        for (int i = start; i < nums.length - 2; i++) {
            int x1 = nums[i];

            //去重
            if (i > start && x1 == nums[i - 1]) {
                continue;
            }
            int tmpTarget = target - x1;
            int low = i + 1, high = nums.length - 1;

            //全部太大了
            if (2 * nums[low] > tmpTarget) {
                break;
            }

            //此次
            if (2 * nums[high] < tmpTarget) {
                continue;
            }

            //夹逼查找
            while (low < high) {

                int tmpSum = nums[low] + nums[high];
                if (tmpSum < tmpTarget) {
                    low++;
                } else if (tmpSum > tmpTarget) {
                    high--;
                } else {
                    ans.add(Arrays.asList(x, x1, nums[low], nums[high]));
                    //去重
                    while (++low < high && nums[low - 1] == nums[low]) ;
                    while (--high > low && nums[high] == nums[high + 1]) ;

                }
            }
        }
    }

}

提高代码质量就是:积累精美的思路,优质的细节的过程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值