• No.016:3Sum Closest


    问题:

    Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target.
    Return the sum of the three integers. You may assume that each input would have exactly one solution.
    For example, given array S = {-1 2 1 -4}, and target = 1.
    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

    官方难度:

    Medium

    翻译:

    给定一个长度为n的无序数组S,找出其中的3个整数,使这3个整数的和最接近于一个给定的目标值,返回这3个整数的和。

    假定整个数组中的解是唯一的。

    例子:

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

    解为2(-1+2+1=2)。

    1. 这题的解法,与No.015(3Sum)的解法基本相同,先排序,然后通过外循环遍历+内循环夹逼的方法实现。
    2. 与3Sum问题不同的是,除了维护上一个值是否与当前值相同,其余的优化方法都不能使用。另外,previous的初始值,不能影响第一次计算。
    3. 维护一个差值closest,这个值要保证是正数。由于解唯一确定,所以在循环过程中,如果出现closest=0的情况,可以直接返回。注意返回值不是差值,而是三个数值的和。
    4. 注意入参检查。

    解题代码:

     1 // 返回值是数组3个元素的和,不是差值
     2     public static int threeSumClosest(int[] nums, int target) {
     3         if (nums == null || nums.length < 3) {
     4             throw new IllegalArgumentException("Input error");
     5         }
     6         Arrays.sort(nums);
     7         // 初始差值和返回值
     8         int returnNo = Integer.MAX_VALUE;
     9         int closest = Integer.MAX_VALUE;
    10         int previous = Integer.MAX_VALUE;
    11         for (int i = 0; i < nums.length - 2; i++) {
    12             if (nums[i] == previous) {
    13                 continue;
    14             }else{
    15                 previous = nums[i];
    16             }
    17             // 数组剩余部分夹逼
    18             int left = i + 1;
    19             int right = nums.length - 1;
    20             // 转化为2Sum Closest问题
    21             int remainTarget = target - nums[i];
    22             int sum;
    23             int preLeft = Integer.MIN_VALUE, preRight = Integer.MIN_VALUE;
    24             while (left < right) {
    25                 if (nums[left] == preLeft) {
    26                     left++;
    27                     continue;
    28                 }
    29                 if (nums[right] == preRight) {
    30                     right--;
    31                     continue;
    32                 }
    33                 sum = nums[left] + nums[right];
    34                 // 解唯一确定,直接返回
    35                 if (remainTarget - sum == 0) {
    36                     return sum + nums[i];
    37                 }
    38                 // 最小值替换,返回值赋值
    39                 int temp = Math.abs(remainTarget - sum);
    40                 if (temp < closest) {
    41                     returnNo = nums[i] + nums[left] + nums[right];
    42                     closest = temp;
    43                 }
    44                 if (remainTarget - sum > 0) {
    45                     left++;
    46                 } else {
    47                     right--;
    48                 }
    49             }
    50         }
    51         return returnNo;
    52     }
    threeSumClosest

    相关链接:

    https://leetcode.com/problems/3sum-closest/

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

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

  • 相关阅读:
    【bzoj2820】GCD
    【learning】莫比乌斯反演
    【bzoj2151】种树
    【noip模拟】局部最小值
    【learning】多项式乘法&fft
    【learning】二分图最大匹配的König定理
    【noip模拟】2048
    【noip模拟】修长城
    【noip模拟】最小点覆盖
    【noip模拟】Fantasia
  • 原文地址:https://www.cnblogs.com/jing-an-feng-shao/p/5959384.html
Copyright © 2020-2023  润新知