Given an integer array arr
and an integer k
, your task is to calculate the mean (average) of the array after removing the smallest k
elements and the largest k
elements. The mean should be returned as a floating-point number. You must not reuse or double-count any elements, and there is always at least one valid solution (i.e., the array is large enough so that after removing 2k
elements, at least one remains).
Constraints:
arr.length
≤ 1000k
< arr.length
/ 2
The first thought is to literally remove the k
smallest and k
largest elements and then compute the mean of what's left. Brute-force would sort the array, slice off the ends, and average the rest. The constraints are small, so a sort is acceptable. However, we should always consider if there's a more efficient way, especially if the problem size were larger.
Since the problem requires removing elements from both ends, sorting is the most direct and reliable method. We don't need to worry about duplicate values or in-place operations, as we can use sorting and slicing. This approach is both simple and effective.
Here is the step-by-step algorithm to solve this problem:
arr
: Sorting arranges all elements in ascending order, making it easy to remove the smallest and largest values.
k
elements: After sorting, the first k
elements are the smallest, and the last k
are the largest. We can exclude these by slicing the array from index k
to len(arr) - k
.
This approach is simple and leverages built-in language features for sorting and slicing, making it both readable and efficient for the given constraints.
Let's walk through an example:
arr = [6, 2, 7, 5, 1, 2, 0, 10, 3, 9]
, k = 2
arr = [0, 1, 2, 2, 3, 5, 6, 7, 9, 10]
[0, 1]
(smallest 2) and [9, 10]
(largest 2). Remaining: [2, 2, 3, 5, 6, 7]
The final answer is approximately 4.1667
.
The key insight is to sort the array, remove the smallest and largest k
elements, and average the rest. This approach is both intuitive and efficient for the problem constraints. Sorting simplifies the removal process, and slicing ensures we do not double-count or reuse elements. The solution is elegant due to its simplicity and directness.
class Solution:
def trimMean(self, arr: List[int], k: int) -> float:
arr.sort()
trimmed = arr[k:len(arr)-k]
return sum(trimmed) / len(trimmed)
class Solution {
public:
double trimMean(vector<int>& arr, int k) {
sort(arr.begin(), arr.end());
int n = arr.size();
int sum = 0;
for (int i = k; i < n - k; ++i) {
sum += arr[i];
}
return (double)sum / (n - 2 * k);
}
};
class Solution {
public double trimMean(int[] arr, int k) {
Arrays.sort(arr);
int n = arr.length;
int sum = 0;
for (int i = k; i < n - k; i++) {
sum += arr[i];
}
return (double) sum / (n - 2 * k);
}
}
var trimMean = function(arr, k) {
arr.sort((a, b) => a - b);
let trimmed = arr.slice(k, arr.length - k);
let sum = trimmed.reduce((a, b) => a + b, 0);
return sum / trimmed.length;
};