Leetcode 1300. Sum of Mutated Array Closest to Target

Problem Explanation

In this problem, we are given an array of integers and a target value. We are required to return an integer value such that, if any number in the array larger than this value is replaced with this value, the sum of the array should be as close to the target value as possible. If we have more than one possible answer, we should return the smallest.

For example, if we have the array [4,9,3] and the target is 10, then the answer is 3. This is because if we replace all the values in the array greater than 3 with 3, we end up with [3,3,3]. The sum of this array is 9, which is the closest we can get to the target of 10.

Explanation of Algorithm and Solution

The algorithm used in this solution is based on sorting. The idea is to iterate through the sorted array and for each number, calculate a candidate answer based on the remaining numbers and the difference between the current sum and the target. If the candidate answer is less than or equal to the current array element, it means we've found our best value, otherwise, we keep checking with the next array element.

On more details, we first sort the array. Then we initialize a variable prefix to 0. This prefix variable will hold the sum of processed elements in the array.

Then we start iterating each element in our sorted array. For each element, we deduct the current prefix from our target, then divide the result by the remaining numbers (the remaining length of the array), rounding to the nearest integer, to find a potential best "value".

If this "value" is less than or equal to the current array element, we know we've found our result and we return it. That's because since the array is sorted, if our calculated "value" is less than the current array element, it will also be less than any subsequent elements.

If our calculated "value" is more than the current array element, we add this element to our prefix and continue to the next element in the array.

If we finish our loop and still haven't found a "value" that is less than any array element, we return the last element in the array as this means our target is higher than any possible sum we can create by replacing elements.

Python Solution

1
2python
3class Solution:
4    def findBestValue(self, arr: List[int], target: int) -> int:
5        arr.sort()
6        prefix = 0
7        for i in range(len(arr)):
8            value = round((target - prefix) / (len(arr) - i))
9            if value <= arr[i]:
10                return value
11            prefix += arr[i]
12        return arr[-1]

Java Solution

1
2java
3class Solution {
4    public int findBestValue(int[] arr, int target) {
5        Arrays.sort(arr);
6        int prefix = 0;
7        for (int i = 0; i < arr.length; i++) {
8            int value = (int) Math.round((double)(target - prefix) / (arr.length - i));
9            if (value <= arr[i]) return value;
10            prefix += arr[i];
11        }
12        return arr[arr.length - 1];
13    }
14}

Javascript Solution

1
2javascript
3var findBestValue = function(arr, target) {
4    arr.sort((a, b) => a - b);
5    let prefix = 0;
6    for (let i = 0; i < arr.length; i++) {
7        let value = Math.round((target - prefix) / (arr.length - i));
8        if (value <= arr[i]) return value;
9        prefix += arr[i];
10    }
11    return arr[arr.length - 1];
12};

C++ Solution

1
2cpp
3class Solution {
4public:
5    int findBestValue(vector<int>& arr, int target) {
6        sort(begin(arr), end(arr));
7        int prefix = 0;
8        for (int i = 0; i < arr.size(); i++) {
9            int value = round((double)(target - prefix) / (arr.size() - i));
10            if (value <= arr[i]) return value;
11            prefix += arr[i];
12        }
13        return arr.back();
14    }
15};

C# Solution

1
2csharp
3public class Solution {
4    public int FindBestValue(int[] arr, int target) {
5        Array.Sort(arr);
6        int prefix = 0;
7        for (int i = 0; i < arr.Length; i++) {
8            int value = (int) Math.Round((double)(target - prefix) / (arr.Length - i));
9            if (value <= arr[i]) return value;
10            prefix += arr[i];
11        }
12        return arr[^1];
13    }
14}

The working of the algorithm is better understood with an example:

Consider the array [4, 5, 7] with a target of 12. First we sort the array. The sorted array is [4, 5, 7].

We start by processing the first array element, 4. The potential value, calculated by (12 - 0) / 3 (rounding) = 4 (12 is target, 0 is prefix and 3 is remaining length). Since 4 is equal to the current array element, 4, we return 4 as our answer.## Conclusion

This algorithm offers a potentially better solution than brute forcing through all possible combinations of numbers in the array. By sorting the array, and considering the elements one by one, we form a potential value based on the remaining target and the remaining elements. We thus find the smallest number that, when replacing all larger numbers in the array, brings us closest to the target sum.

The algorithm has a time complexity of O(N log(N)) due to the sorting operation, where N is the size of the input array. The space complexity is O(1) as we only use a few variables to store intermediate calculation results.

The Python, Java, JavaScript, C++, and C# versions of the solution are identical in logic, with minor syntax differences due to the characteristics of each programming language. The algorithm can also be easily adapted to other programming languages that supports basic data structure and mathematical operations.

Hence, the problem of finding the best value for an array replacement to achieve a target sum demonstrates the application of sorting and progressive calculation in programming problem-solving. And this kind of problems can be seen in software development for applications ranging from data analysis, game design, to even machine learning, wherever there's a need to optimize a particular value based on constraints.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫