zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    vue——学习笔记
    工作笔记——上传图片
    前端调试利器——BrowserSync
    工作笔记——一些常用函数的封装
    【html、CSS、javascript-3】几个基本元素
    【html、CSS、javascript-2】CSS基础
    【html、CSS、javascript-1】html基础
    【python之路37】with上下文管理
    【python之路36】进程、线程、协程相关
    【python之路35】FTP文件断电续传作业
  • 原文地址:https://www.cnblogs.com/zpfbuaa/p/6505836.html
Copyright © 2011-2022 走看看