原题目:https://leetcode-cn.com/problems/sum-of-mutated-array-closest-to-target/
思路:
可以发现该题是二分查找。我们的任务是查找符合条件的value,具体的思路如下:
因为target的值是非负正整数,所以value的下界是0.value的上界是数组中的最大值。我们可以二分查找value的值。
然后在排好需的arr数组中,采用二分查找,找到第一个<=value的值,则变换后的数组的和为
sum = arr[i]+...arr[i] + value*(arr.size()-i);为了不重复计算,我们可以用一个数组保存arr的前缀和。
注意:sum的值是随value严格递增的。
value对应的sum有两种情况。一种是≤target,一种是大于target。在每次的循环中都保存和≤target的value,最后的value对应的sum一定是等于target或者小于target的最接近于target的值。
那么最后应该返回什么?容易知道,我们可以返回value和value+1对应的sum和target差值最小的那个。
class Solution {
public:
int check(const vector<int>& arr, int x) {
int ret = 0;
for (const int& num: arr) {
ret += (num >= x ? x : num);
}
return ret;
}
int findBestValue(vector<int>& arr, int target) {
sort(arr.begin(), arr.end());
int n = arr.size();
vector<int> prefix(n + 1);
for (int i = 1; i <= n; ++i) {
prefix[i] = prefix[i - 1] + arr[i - 1];
}
int l = 0, r = arr[arr.size()-1], ans = -1;
//二分查找满足条件的数。
while (l <= r) {
int mid = (l + r) / 2;
//二分查找,找到第一个>=mid的值,通过begin() - iter.可以返回该值的下标。
auto iter = lower_bound(arr.begin(), arr.end(), mid);
int cur = prefix[iter - arr.begin()] + (arr.end() - iter) * mid;
if (cur <= target) {
ans = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
int choose_small = check(arr, ans);
int choose_big = check(arr, ans + 1);
return abs(choose_small - target) <= abs(choose_big - target) ? ans : ans + 1;
}
};
代码: