跳至主要內容

最靠近目标数的三数


最靠近目标数的三数

题目

给定一个未排序数数组和一个目标数,在数组中找到一个和尽可能接近目标数的三元组,返回该三元组的和。如果这样的三元组不止一个,则返回具有最小和的三元组的和。

示例1:

输入:[-2, 0, 1, 2], target=2
输出:1
解释:[-2, 1, 2]是最靠近2的三元组

示例2:

输入:[-3, -1, 1, 2], target=1
输出:0
解释:[-3, 1, 2]是最靠近1的三元组

解答1:

import java.util.*;

class TripletSumCloseToTarget {

  public static int searchTriplet(int[] arr, int targetSum) {
    if (arr == null || arr.length < 3)
      throw new IllegalArgumentException();

    Arrays.sort(arr);
    int smallestDifference = Integer.MAX_VALUE;
    for (int i = 0; i < arr.length - 2; i++) {
      int left = i + 1, right = arr.length - 1;
      while (left < right) {
        //将三个数字的和与'targetSum'进行比较可能会导致溢出
        //因此,我们试图去找到一个目标差异
        int targetDiff = targetSum - arr[i] - arr[left] - arr[right];
        if (targetDiff == 0) //找到和为targetSum的三元组
          return targetSum - targetDiff; //返回所有元素的和

        // 下面的判定条件的第二部分是为了解决重复三元组的问题,
        //在于targetSum差值相等的情况下,targetDiff>smallestDifference时,
        //三数之和越小(target=targetDiff+三数之和)
        if (Math.abs(targetDiff) < Math.abs(smallestDifference)
            || (Math.abs(targetDiff) == Math.abs(smallestDifference) && targetDiff > smallestDifference))
          smallestDifference = targetDiff; //保存该targetDiff

        if (targetDiff > 0)
          left++; //我们将left指针右移来得到一个更大的数,从而得到更大的currentSum
        else
          right--; //我们将right指针左移来得到一个更小的数,从而得到更小的currentSum
      }
    }
    return targetSum - smallestDifference;
  }

  public static void main(String[] args) {
    System.out.println(TripletSumCloseToTarget.searchTriplet(new int[] { -2, 0, 1, 2 }, 2));
    System.out.println(TripletSumCloseToTarget.searchTriplet(new int[] { -3, -1, 1, 2 }, 1));
    System.out.println(TripletSumCloseToTarget.searchTriplet(new int[] { 1, 0, 1, 1 }, 100));
  }
}
上次编辑于:
贡献者: Neil