Given an integer array arr
and a target value target
, return the integer value
such that when we change all the integers larger than value
in the given array to be equal to value
, the sum of the array gets as close as possible (in absolute difference) to target
.
In case of a tie, return the minimum such integer.
Notice that the answer is not necessarily a number from arr
.
Example 1:
Input: arr = [4,9,3], target = 10 Output: 3 Explanation: When using 3 arr converts to [3, 3, 3] which sums 9 and that's the optimal answer.Example 2:
Input: arr = [2,3,5], target = 10 Output: 5Example 3:
Input: arr = [60864,25176,27249,21296,20204], target = 56803 Output: 11361
Constraints:
1 <= arr.length <= 10^4
1 <= arr[i], target <= 10^5
转变数组后最接近目标值的数组和。题意是给一个数组和一个数字target,请你返回一个整数value,使得数组中所有比这个value大的数字被换成value之后,数组中所有数字的和sum最接近于target。比如第一个例子,把所有大于3的数字换成3之后,数组的和是9,最接近于给定的target10。
思路是二分法。首先遍历input数组,得到数组所有元素的和sum以及数组中最大的数字max。需要寻找的这个res一定介于0 - max之间。为什么呢?因为被修改的数字一定是需要小于value的,如果这个value大于数组中的最大元素,意味着没有任何一个数字被修改过,所以value大于max是不成立的。所以在0 - max之间做二分搜索,并且每找到一个mid,就算一次sum和,二分法逼近最接近target的sum之后,找到对应的mid即可。
时间O(nlogn)
空间O(1)
Java实现
1 class Solution { 2 public int findBestValue(int[] arr, int target) { 3 int sum = 0; 4 int max = Integer.MIN_VALUE; 5 for (int a : arr) { 6 sum += a; 7 max = Math.max(max, a); 8 } 9 if (sum == target) return max; 10 int min = 0, res = 1,diff = Integer.MAX_VALUE; 11 // The answer would lie between 0 and maximum value in the array. 12 while (min <= max) { 13 int mid = min + (max - min) / 2; 14 sum = getMutatedSum(arr, mid); 15 if (sum > target) { 16 max = mid - 1; 17 } else { 18 min = mid + 1; 19 } 20 // If current difference is less than diff || current difference==diff but mid < res.(choose the smaller one.) 21 if (Math.abs(sum - target) < diff || (Math.abs(sum - target) == diff && mid < res)) { 22 res = mid; 23 diff = Math.abs(sum - target); 24 } 25 } 26 return res; 27 } 28 29 private int getMutatedSum(int[] arr, int mid) { 30 int sum = 0; 31 for (int a : arr) { 32 sum += (a > mid) ? mid : a; 33 } 34 return sum; 35 } 36 }