题目
给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target (最接近表示两者之差的绝对值最小)。
如果有多种使得和最接近 target 的方案,请你返回这些整数中的最小值。
请注意,答案不一定是 arr 中的数字。链接
思路
一开始想用平均数,但是数组中不是所有元素都需要变为value
。。
确定value的取值范围为[0,max(arr)]
设为threshold
,则需要确定使得数组元素超过threshold
的元素变为threshold
后数组和的值最接近target
,可通过二分查找出严格大于target
的第一个threshold
,在通过比较threshold
与threshold-1
的数组和,即可确定结果。
class Solution {
public int findBestValue(int[] arr, int target) {
int left=0,right=0;
for(int x:arr){
right=Math.max(right,x);
}
while(left<right){
int mid=left+(right-left)/2;
if(calSum(arr,mid)<target){
left=mid+1;
}else{
right=mid;
}
}
/*
这里left为第一个使数组和大于target的threshold
则left-1必然使得数组和小于target,即判断这两个哪个接近target
*/
if(target-calSum(arr,left-1)<=calSum(arr,left)-target){
return left-1;
}
return left;
}
int calSum(int[]arr,int threshold){
int sum=0;
for(int x:arr){
sum+=Math.min(threshold,x);
}
return sum;
}
}