Sum of Mutated Array Closest to Target

Binary search the cap value that, after clamping every element, makes the array sum closest to target.

Medium
Time O(n log M) Space O(1)
LeetCode
5 min read
binary-search parametric-search

Problem#

Given an integer array arr and target, find a non-negative integer value such that replacing every element greater than value with value makes the sum closest to target. If two values tie, return the smaller.

Examples#

  • arr = [4,9,3], target = 103 (sum becomes 3+3+3 = 9, closest to 10)
  • arr = [2,3,5], target = 105
  • arr = [60864,25176,27249,21296,20204], target = 5680311361

Constraints#

  • 1 <= arr.length <= 10^4, 1 <= arr[i], target <= 10^5.

Approach#

The clipped sum is monotonic in value. Binary search value over [0, max(arr)] and pick the boundary point. Compare |sum(value) - target| vs |sum(value-1) - target|, returning the smaller value on tie.

Solution#

Sum of Mutated Array Closest to Target
class Solution {
public:
int findBestValue(vector<int>& arr, int target) {
auto clipSum = [&](int v) {
long s = 0;
for (int x : arr) s += min(x, v);
return s;
};
int lo = 0, hi = *max_element(arr.begin(), arr.end());
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (clipSum(mid) < target) lo = mid + 1;
else hi = mid;
}
long sHi = clipSum(lo), sLo = clipSum(lo - 1);
if (abs(sLo - target) <= abs(sHi - target)) return lo - 1;
return lo;
}
};

Editorial#

Clipping is non-decreasing in value, so the first v where clipSum(v) >= target is the binary-search boundary. The optimal answer is either that v or v-1. On a tie in distance, the smaller value wins per the problem spec.

Complexity#

  • Time: O(n log M) where M = max(arr).
  • Space: O(1).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.