给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target (最接近表示两者之差的绝对值最小)。
如果有多种使得和最接近 target 的方案,请你返回这些整数中的最小值。
请注意,答案不一定是 arr 中的数字。
示例 1:
输入:arr = [4,9,3], target = 10
输出:3
解释:当选择 value 为 3 时,数组会变成 [3, 3, 3],和为 9 ,这是最接近 target 的方案。
示例 2:输入:arr = [2,3,5], target = 10
输出:5
示例 3:输入:arr = [60864,25176,27249,21296,20204], target = 56803
输出:11361
提示:
1 <= arr.length <= 10^4
1 <= arr[i], target <= 10^5
https://leetcode.cn/problems/sum-of-mutated-array-closest-to-target/
利用二分查找可以得到满足条件的值,但是不满足多种方案去最小值的要求,这里需要在二分中寻找。
int findBestValue(vector<int>& arr, int target) {
sort(arr.begin(),arr.end());
vector<int>presum(arr.size()+5);
presum[0]=0;
for(int i=1;i<=arr.size();i++)
{
presum[i]=presum[i-1]+arr[i-1];//前缀和以1下标为起点,防止溢出讨论
}
int l=1,r=*max_element(arr.begin(),arr.end()),ans=INT_MAX,index=0;
while(l<r)
{
int mid=(l+r)/2;
int k=upper_bound(arr.begin(),arr.end(),mid)-arr.begin();//大于mid点的下标
int cur=presum[k]+mid*(arr.size()-k);
if(cur<target)
{
int x=upper_bound(arr.begin(),arr.end(),mid+1)-arr.begin();//大于mid+1
int y=presum[x]+(mid+1)*(arr.size()-x);
if(abs(cur-target)<=ans)
{
if(abs(cur-target)<ans)
{
ans=abs(cur-target);index=mid;
}
else if(abs(cur-target)==ans&&mid<index)index=mid;
} //在mid和mid+1中寻找
if(abs(y-target)<=ans)
{
if(abs(y-target)<ans)
{
ans=abs(y-target);index=mid+1;
}
else if(abs(y-target)==ans&&mid+1<index)index=mid+1;
}
l=mid+1;
}
else r=mid;
}
return index;
}