• LeetCode 18 4Sum (4个数字之和等于target)


    题目链接 https://leetcode.com/problems/4sum/?tab=Description

    找到数组中满足 a+b+c+d=0的所有组合,要求不重复。

    Basic idea is using subfunctions for 3sum and 2sum, and keeping throwing all impossible cases. O(n^3) time complexity, O(1) extra space complexity.

    首先进行判断,由于是四个数相加等于target,其中可以通过判断剪去一些不必要的分支:

    for (i = 0; i < len; i++) {
                z = nums[i];
                if (i > 0 && z == nums[i - 1])// avoid duplicate
                    continue;
                if (z + 3 * max < target) // z is too small
                    continue;
                if (4 * z > target) // z is too large
                    break;
                if (4 * z == target) { // z is the boundary
                    if (i + 3 < len && nums[i + 3] == z)
                        res.add(Arrays.asList(z, z, z, z));
                    break;
                }
    
                threeSumForFourSum(nums, target - z, i + 1, len - 1, res, z);
            }

    进入3个数相加的同时,需要对target进行更新。

    for (i = low; i < high - 1; i++) {
                z = nums[i];
                if (i > low && z == nums[i - 1]) // avoid duplicate
                    continue;
                if (z + 2 * max < target) // z is too small
                    continue;
    
                if (3 * z > target) // z is too large
                    break;
    
                if (3 * z == target) { // z is the boundary
                    if (i + 1 < high && nums[i + 2] == z)
                        fourSumList.add(Arrays.asList(z1, z, z, z));
                    break;
                }
    
                twoSumForFourSum(nums, target - z, i + 1, high, fourSumList, z1, z);
            }

    进入两个数相加时,问题得到进一步简化。

    int i = low, j = high, sum, x;
            while (i < j) {
                sum = nums[i] + nums[j];
                if (sum == target) {
                    fourSumList.add(Arrays.asList(z1, z2, nums[i], nums[j]));
    
                    x = nums[i];
                    while (++i < j && x == nums[i]) // avoid duplicate
                        ;
                    x = nums[j];
                    while (i < --j && x == nums[j]) // avoid duplicate
                        ;
                }
                if (sum < target)
                    i++;
                if (sum > target)
                    j--;
            }

    参考代码:

    package leetcode_50;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /***
     * 
     * @author pengfei_zheng
     * 四个数加法等于target
     */
    public class Solution18 {
        public List<List<Integer>> fourSum(int[] nums, int target) {
            ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
            int len = nums.length;
            if (nums == null || len < 4) //不足4个元素
                return res;
    
            Arrays.sort(nums);//排序
    
            int max = nums[len - 1];
            if (4 * nums[0] > target || 4 * max < target)//4个最小值之和超过target或者4个最大值之和小于target
                return res;
    
            int i, z;
            for (i = 0; i < len; i++) {
                z = nums[i];
                if (i > 0 && z == nums[i - 1])// avoid duplicate
                    continue;
                if (z + 3 * max < target) // z is too small
                    continue;
                if (4 * z > target) // z is too large
                    break;
                if (4 * z == target) { // z is the boundary
                    if (i + 3 < len && nums[i + 3] == z)
                        res.add(Arrays.asList(z, z, z, z));
                    break;
                }
    
                threeSumForFourSum(nums, target - z, i + 1, len - 1, res, z);
            }
    
            return res;
        }
    
        public void threeSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList,
                int z1) {
            if (low + 1 >= high)
                return;
    
            int max = nums[high];
            if (3 * nums[low] > target || 3 * max < target)
                return;
    
            int i, z;
            for (i = low; i < high - 1; i++) {
                z = nums[i];
                if (i > low && z == nums[i - 1]) // avoid duplicate
                    continue;
                if (z + 2 * max < target) // z is too small
                    continue;
    
                if (3 * z > target) // z is too large
                    break;
    
                if (3 * z == target) { // z is the boundary
                    if (i + 1 < high && nums[i + 2] == z)
                        fourSumList.add(Arrays.asList(z1, z, z, z));
                    break;
                }
    
                twoSumForFourSum(nums, target - z, i + 1, high, fourSumList, z1, z);
            }
    
        }
    
        public void twoSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList,
                int z1, int z2) {
    
            if (low >= high)
                return;
    
            if (2 * nums[low] > target || 2 * nums[high] < target)
                return;
    
            int i = low, j = high, sum, x;
            while (i < j) {
                sum = nums[i] + nums[j];
                if (sum == target) {
                    fourSumList.add(Arrays.asList(z1, z2, nums[i], nums[j]));
    
                    x = nums[i];
                    while (++i < j && x == nums[i]) // avoid duplicate
                        ;
                    x = nums[j];
                    while (i < --j && x == nums[j]) // avoid duplicate
                        ;
                }
                if (sum < target)
                    i++;
                if (sum > target)
                    j--;
            }
            return;
        }
    }
    Full Code
  • 相关阅读:
    【转】解决在Android设备播放音频与其他应用重音的问题,并监听耳机的控制按钮
    【转】wamp 3.0.6(apache 2.4.23) 403 forbidden 解决办法
    身份证第18位(校验码)的计算方法
    【转】Win10开机密码忘了?教你破解Win10开机密码
    【转】具透 | 你可能不知道,iOS 10 有一个中国「特供」的联网权限功能
    钉钉自定义机器人 发送文本 换行 无效果
    屏蔽右键+f12
    【转】理解WebKit和Chromium: JavaScript引擎简介
    第2章 排序 | 第10节 计数排序练习题 && 基数排序
    图像处理-深入探索插值操作
  • 原文地址:https://www.cnblogs.com/zpfbuaa/p/6505836.html
Copyright © 2020-2023  润新知