Problem overview
The function trimmed_total receives a vector of integers, nums, with 3 to 100 numbers between -1000 and 1000. It returns their sum without the smallest and the largest value. This is how some contests score: each judge gives a number, and the lowest and highest are dropped so that one very strict or very kind judge cannot decide alone.
Only one smallest and one largest value are dropped. If the smallest value appears twice, the other copy still counts, and the same goes for the largest.
For [7, 9, 6, 8, 10] the answer is 24: the 6 and the 10 are dropped, and 7 + 9 + 8 remain. For [5, 1, 5, 9, 1] it is 11, because only one 1 and the 9 are dropped. For [-4, 3, -2] it is -2.
Approach
Add everything, then take away the two extremes. Subtracting the smallest value once and the largest value once removes exactly one smallest and one largest item, even when those values repeat. The iterator methods sum(), min() and max() do the work, so no loop is needed.
Step by step
- Total.
let total: i32 = nums.iter().sum();adds the numbers. The type ontotalis required:sum()can produce several number types, and without a type the compiler reports "type annotations needed". - Smallest.
nums.iter().min()returns anOption, because an empty vector has no smallest value.unwrap()takes the value out; here it always exists, since there are at least 3 numbers. The value is a reference, so a*in front gives the plain number. - Largest. The same chain with
max(). When the largest value appears twice,max()still gives that value once. - Return
total - smallest - largest.
The solution in Rust
impl Solution {
fn trimmed_total(nums: Vec<i32>) -> i32 {
let total: i32 = nums.iter().sum();
let smallest = *nums.iter().min().unwrap();
let largest = *nums.iter().max().unwrap();
return total - smallest - largest;
}
}
The sum is at most 100 times 1000 in size, so an i32 holds it without overflow. The function is safe to unwrap() only because of the constraint of at least 3 numbers; on an empty vector the same code would panic.
Another way
Sorting a copy puts the extremes at both ends, so the middle slice is the answer:
let mut sorted = nums.clone();
sorted.sort();
let middle: i32 = sorted[1..sorted.len() - 1].iter().sum();
It gives 24, 11 and -2 on the three examples, like the lesson's version. The solution above is simpler and does not need to sort or copy anything. Sorting would also reorder the numbers, which this problem does not need.
The three examples give:
24
11
-2
Edge cases and common mistakes
- Removing every copy. Filtering out all values equal to the smallest would drop both 1s in the second example and give 10, not 11. Subtracting each extreme once is the right rule.
- Negative numbers. The third example subtracts -4 and 3 from -3, and the arithmetic works the same way.
- Calling
min()on an empty vector. It returnsNone, andunwrap()onNonepanics. The constraint of at least 3 numbers rules this out here.
