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 neccesarilly 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: 5
Example 3:
Input: arr = [60864,25176,27249,21296,20204], target = 56803 Output: 11361
Constraints:
1 <= arr.length <= 10^4
1 <= arr[i], target <= 10^5
题目链接:https://leetcode.com/problems/sum-of-mutated-array-closest-to-target/
题目大意:给一个数组,求一个value使数组中大于value的数都变成value,要求变化后数组值得和尽可能可target接近
题目分析:排序后求前缀和,若当前总和小于等于target,直接选最大的数即可,否则二分答案(需要保证二分的答案不大于target,对于最终总和可能大于target的情况只需对最后得出的二分答案加1再比较即可),判断时需再次利用二分找当前二分的答案在原数组中的位置,从而算出当前二分的答案可使总和变成多少
6ms,时间击败38.55%
class Solution {
private int bsearch2(int[] arr, int x) {
int l = 0, r = arr.length - 1, mid = 0, ans = -1;
while (l <= r) {
mid = (l + r) >> 1;
if (arr[mid] <= x) {
l = mid + 1;
ans = mid;
} else {
r = mid - 1;
}
}
return ans;
}
private int calSum(int[] arr, int val, int[] presum) {
int idx = bsearch2(arr, val);
int pres = idx == -1 ? 0 : presum[idx];
return pres + val * (arr.length - idx - 1);
}
private int bsearch(int[] arr, int target, int[] presum) {
int n = arr.length, l = 1, r = target, mid = 0, ans = 0;
while (l <= r) {
mid = (l + r) >> 1;
int sum = calSum(arr, mid, presum);
if (sum > target) {
r = mid - 1;
} else if (sum < target) {
l = mid + 1;
ans = mid;
} else {
return mid;
}
}
return ans;
}
public int findBestValue(int[] arr, int target) {
Arrays.sort(arr);
int n = arr.length;
int[] presum = new int[n];
presum[0] = arr[0];
for (int i = 1; i < n; i++) {
presum[i] = presum[i - 1] + arr[i];
}
if (presum[n - 1] <= target) {
return arr[n - 1];
}
int val1 = bsearch(arr, target, presum), val2 = val1 + 1;
int sum1 = calSum(arr, val1, presum);
int sum2 = calSum(arr, val2, presum);
if (Math.abs(target - sum1) <= Math.abs(target - sum2)) {
return val1;
}
return val2;
}
}