Problem overview
trimmedTotal(nums) receives an array of 3 to 100 integers and returns their sum without the smallest and the largest value. Contests score this way: every judge gives a score, and the lowest and the highest are dropped, so one very strict or very kind judge can't decide alone.
Only one smallest value and one largest value are dropped. For [7, 9, 6, 8, 10] the smallest is 6 and the largest 10, so the rest add up to 7 + 9 + 8 = 24. For [5, 1, 5, 9, 1] the smallest, 1, appears twice. Only one 1 is dropped, and so is the 9, leaving 5 + 5 + 1 = 11.
Approach
Add everything, then subtract the smallest once and the largest once. Subtracting each value a single time removes exactly one copy of it, even when it repeats. Nothing needs sorting or searching for positions.
The three pieces are built-ins: reduce for the total, and Math.min and Math.max with the spread dots for the extremes.
Step by step
- Store the sum of all numbers in
total:nums.reduce((sum, x) => sum + x, 0). - Store the smallest number in
smallestwithMath.min(...nums). - Store the largest number in
largestwithMath.max(...nums). - Return
total - smallest - largest.
The solution in JavaScript
class Solution {
/**
* @param {number[]} nums
* @return {number}
*/
trimmedTotal(nums) {
let total = nums.reduce((sum, x) => sum + x, 0);
let smallest = Math.min(...nums);
let largest = Math.max(...nums);
return total - smallest - largest;
}
}
The dots in ...nums spread the array into separate arguments, which is what Math.min and Math.max expect. Without them they would be handed the whole array and give NaN for arrays with more than one number. The three examples return:
24
11
-2
For the second example, the total is 21, the smallest is 1 and the largest is 9, so 21 - 1 - 9 = 11. The third example, [-4, 3, -2], adds to -3, minus the smallest -4 and the largest 3, gives -2: subtracting a negative number adds it back.
Testing
Besides the statement's examples, try the smallest allowed input, three numbers such as [1, 2, 3]: the smallest is 1, the largest is 3, and what is left is 2. Try three equal numbers such as [4, 4, 4]: the total is 12, and subtracting one 4 for the smallest and one 4 for the largest leaves 4. In both cases exactly one value remains, which is the middle one.
Complexity
The sum, the minimum and the maximum each read the array once, so the time is O(n). The extra space is O(1) for the three numbers you keep; the spread also hands the values to the function as separate arguments, which is fine for at most 100 numbers.
Edge cases and common mistakes
- Dropping every copy. Removing all copies of the smallest value would turn the second example into 5 + 5 = 10. Subtracting
smallestonce keeps the other 1. - Sorting and slicing. Sorting without a compare function orders numbers as text, so
[10, 9, 1].sort()gives[1, 10, 9]. Subtracting the extremes avoids that. - Forgetting the start value of
reduce. Here the input always has at least 3 numbers, so a missing0would not crash. Pass it anyway: it makes the sum start from a known place, and an empty array would otherwise throw aTypeError. - Leaving out the dots.
Math.min(nums)givesNaNfor this input.
