给你一个整数数组 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

思路:
首先进行排序,让数据符合可二分性,求得前缀和,二分大小的下标做为条件求和,然后再二分答案,整体时间复杂度 leetcode 1300. 转变数组后最接近目标值的数组和(前缀和+二分)_i++

写了40~50分钟的代码:仅供参考

#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long ll;
const int inf = 1 << 30;
const int maxn = 2e5 + 5;
const int N = 1e3 + 5;
const int base = 131;
//vector<vector<int>> vec;
int a[maxn], sum[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, target;
cin >> n >> target;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + a[i];
int l = 0, r = 100000000, minx = 200000000;
int ans = a[n];
if (sum[n] <= target)
{
cout << ans << endl;
return 0;
}
while (l <= r)
{
int mid = (l + r) >> 1;
int x = lower_bound(a + 1, a + 1 + n, mid) - a;
int su = sum[x - 1] + (n - x + 1) * mid;
if (abs(su - target) < minx)
minx = abs(su - target), ans = mid;
else if (abs(su - target) == minx)
ans = min(ans, mid);
if (su >= target)
r = mid - 1;
else
l = mid + 1;
}
cout << ans << endl;
}

以leetcode形式提交:

class Solution {
int a[10005], sum[10005];
public:
int findBestValue(vector<int>& arr, int target) {
int n=arr.size();
for (int i = 1; i <= n; i++)
a[i]=arr[i-1];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + a[i];
int l = 0, r = 100000000, minx = 200000000;
int ans = r;
if(sum[n]<=target)
return a[n];
while (l <= r)
{
int mid = (l + r) >> 1;
int x = lower_bound(a + 1, a + 1 + n, mid) - a;
int su = sum[x - 1] + (n - x + 1) * mid;
if (abs(su - target) < minx)
minx = abs(su - target), ans = mid;
else if (abs(su - target) == minx)
ans = min(ans, mid);
if (su >= target)
r = mid - 1;
else
l = mid + 1;
} return ans;
}
};