Problem overview
The method dropEnds gets an ArrayBuffer[Int] named nums with at least two numbers. It returns a new buffer with every number except the first and the last, in the same order.
For [4, 8, 15, 16, 23] the ends are 4 and 23, so the result is [8, 15, 16]. For [9, 0, 9] only the 0 is between the ends, so the result is [0]. For [1, 2] there is nothing between the ends, and the result is empty.
Approach
The numbers to keep sit at indexes 1 up to the last index minus one. slice(i, j) copies from index i up to but not including j, so both ends take care of themselves:
- starting at index 1 leaves out the first number;
- ending at
nums.size - 1leaves out the last number, because the last number sits at indexnums.size - 1and the end index is excluded.
With five numbers the slice is slice(1, 4): indexes 1, 2 and 3.
Step by step
- Slice from 1 to
nums.size - 1and store the copy in avalnamedmiddle. - Return
middle. With two numbers it isslice(1, 1), which is empty: nothing lies between the ends.
Tracing one input
Take nums = [3, 8, 1, 9, 4]. Its size is 5, so the last index is 4 and the call is nums.slice(1, 5 - 1), that is slice(1, 4). The result is ArrayBuffer(8, 1, 9). The 3 at index 0 is skipped because the slice starts at index 1, and the 4 at index 4 is skipped because the slice stops before index 4. Nothing else needs to be checked, so the method has no loop and no if.
The solution in Scala
class Solution {
def dropEnds(nums: ArrayBuffer[Int]): ArrayBuffer[Int] = {
val middle = nums.slice(1, nums.size - 1)
return middle
}
}
Details worth knowing:
sizeis the number of items, so the last index issize - 1. Usingsize - 1as the end of a slice therefore stops just before the last item.- The result is a copy.
numsstill has all its numbers afterwards. - Scala's
slicenever throws for a range that holds nothing. Even a buffer with one number gives an empty result:ArrayBuffer(7).slice(1, 0)printsArrayBuffer(). The constraints guarantee at least two numbers anyway.
Edge cases and common mistakes
- Exactly two numbers. The result is empty, and the empty buffer is a correct answer.
- Ending at
nums.size. That keeps the last number. The end must benums.size - 1. - Starting at 0. That keeps the first number. Start at 1.
- Equal ends. In
[9, 0, 9]both ends have the same value. Slicing works by position, not value, so it is not confused by that.
If you ever need the same slice for a buffer that might have fewer than two numbers, slice keeps you safe: there is no index to go out of range, only an empty answer.
Another way
You can say the same thing by name: nums.drop(1).dropRight(1) removes one item from the front, then one from the back, and gives ArrayBuffer(8, 1, 9) for [3, 8, 1, 9, 4]. For a buffer of two numbers it gives an empty buffer, as slice does. The version with slice says exactly which indexes you keep, which makes it easier to check by hand.
Testing
[4, 8, 15, 16, 23] -> 8 15 16
[9, 0, 9] -> 0
[1, 2] -> (empty)
