zoukankan      html  css  js  c++  java
  • No.018:4Sum

    问题:

    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]

    ]

    官方难度:

    Medium

    翻译:

    给定一个长度为n的无序数组S和目标数字target,在数组S中找出4个整数a,b,c,d,使a+b+c+d=target。

    找出所有的可能解,且解集中不包含重复项。

    例子:

    数组S:{ 1, 0, -1, 0, -2, 2},目标值target=0。

    解集为[ [-1,0,0,1],[-2,-1,1,2],[-2,0,0,2] ]。

    1. 显然,本题是No.001(Two Sum),No.015(3Sum),No.016(3Sum Closest)更深一步的讨论。在解决这道问题时,不妨考虑一种解法,适用于5Sum,6Sum之后一系列的问题。我可以将这些问题总结归纳为:kSum问题,k>=2。
    2. 显然是需要使用递归,而递归的终点就是2Sum问题。
    3. 将递归方法独立出来,在进入递归之前,优先给数组排序(如k=2,这种做法会略微影响性能)。
    4. 2Sum问题,仍然使用夹逼的原则,同时维护两侧的previous值。增加优化策略:当前左值大于目标数且当前左值大于0,return;当2倍前左值大于目标值,或2倍当前右值小于目标值,return。
    5. 当k>2时,做类似2Sum的优化策略,将当前目标值-当前值,作为递归入参的目标值,同时传入当前索引值,进行递归。
    6. 获得递归的解集,循环加入当前值到解集中返回。
    7. 注意入参检查。

    解题代码:

     1     public static List<List<Integer>> fourSum(int[] nums, int target) {
     2         if (nums == null || nums.length < 4) {
     3             throw new IllegalArgumentException("Input error");
     4         }
     5         Arrays.sort(nums);
     6         return kSum(nums, 0, target, 4);
     7     }
     8 
     9     private static List<List<Integer>> kSum(int[] nums, int startIndex, int target, int kSum) {
    10         List<List<Integer>> result = new LinkedList<>();
    11         // 递归终点是2Sum问题
    12         if (kSum == 2) {
    13             int left = startIndex, right = nums.length - 1;
    14             int preLeft = Integer.MIN_VALUE, preRight = Integer.MIN_VALUE;
    15             while (left < right) {
    16                 if (nums[left] > target && nums[left] > 0) {
    17                     return result;
    18                 }
    19                 if (2 * nums[left] > target || 2 * nums[right] < target) {
    20                     return result;
    21                 }
    22                 if (nums[left] == preLeft) {
    23                     left++;
    24                     continue;
    25                 }
    26                 if (nums[right] == preRight) {
    27                     right--;
    28                     continue;
    29                 }
    30                 int sum = nums[left] + nums[right];
    31                 if (sum == target) {
    32                     List<Integer> list = new LinkedList<>();
    33                     list.add(nums[left]);
    34                     list.add(nums[right]);
    35                     result.add(list);
    36                 }
    37                 if (sum < target) {
    38                     preLeft = nums[left];
    39                     left++;
    40                 } else {
    41                     preRight = nums[right];
    42                     right--;
    43                 }
    44             }
    45         } else {
    46             // 大于2Sum问题,使用递归
    47             int previous = Integer.MAX_VALUE;
    48             for (int i = startIndex; i < nums.length - 1; i++) {
    49                 if (nums[i] > target && nums[i] > 0) {
    50                     return result;
    51                 }
    52                 // target值的范围超过k个极值
    53                 if (kSum * nums[i] > target || kSum * nums[nums.length - 1] < target) {
    54                     return result;
    55                 }
    56                 if (nums[i] == previous) {
    57                     continue;
    58                 }
    59                 int tempTarget = target - nums[i];
    60                 // 开启递归
    61                 List<List<Integer>> tempResult = kSum(nums, i + 1, tempTarget, kSum - 1);
    62                 for (List<Integer> a : tempResult) {
    63                     a.add(nums[i]);
    64                     result.add(a);
    65                 }
    66                 previous = nums[i];
    67             }
    68         }
    69         return result;
    70     }
    fourSum

    相关链接:

    https://leetcode.com/problems/4sum/

    https://github.com/Gerrard-Feng/LeetCode/blob/master/LeetCode/src/com/gerrard/algorithm/medium/Q018.java

    PS:如有不正确或提高效率的方法,欢迎留言,谢谢!

  • 相关阅读:
    iOS cannot find folder xcdatamodeld Xcode 7
    ios swift generator 文章推荐
    ios swift 2 新的OptionSetType使用方法
    Maven 教程(11)— Maven远程仓库的各种配置
    Maven 教程(10)— Maven依赖详解
    Maven 教程(9)— Maven坐标详解
    Maven设置MAVEN_OPTS环境变量
    Maven 教程(7)— Maven使用的最佳实践
    Maven 教程(6)— Maven之pom.xml文件简单说明
    Maven 教程(5)— Maven目录结构及常用命令说明
  • 原文地址:https://www.cnblogs.com/jing-an-feng-shao/p/5973421.html
Copyright © 2011-2022 走看看