Problem overview
The function dropEnds gets a MutableList<Int> called nums with at least two numbers. It returns everything except the first and the last number, keeping the order of the rest. With exactly two numbers, nothing is between the ends, so the result is empty.
For [4, 8, 15, 16, 23] the ends are 4 and 23, and the answer is [8, 15, 16]. For [9, 0, 9] only the 0 is left, and for [1, 2] the result is empty.
Approach
The first number is at index 0, so the slice starts at index 1. The last number is at index nums.size - 1. Because the end index of subList is excluded, using nums.size - 1 as the end leaves that last number out. The slice subList(1, nums.size - 1) is therefore the middle, and with two numbers it is subList(1, 1), which is empty.
Step by step
- Take the middle. Call
subListwith 1 andnums.size - 1and keep the result in avalnamedmiddle. - Return it.
The solution in Kotlin
class Solution {
fun dropEnds(nums: MutableList<Int>): MutableList<Int> {
val middle = nums.subList(1, nums.size - 1)
return middle
}
}
On the three examples it gives (values separated by spaces):
8 15 16
0
(empty line)
As with any subList, the result is a view of nums rather than a copy. Reading it is fine for this lesson. Add .toMutableList() if you want a list that is independent of nums.
Another way
Kotlin's nums.lastIndex is the same as nums.size - 1, so this version reads a little more clearly:
fun dropEnds(nums: MutableList<Int>): MutableList<Int> = nums.subList(1, nums.lastIndex)
Another version builds a new list in two steps, nums.drop(1).dropLast(1).toMutableList(). Both give [8, 15, 16] for the first example and [] for [1, 2]. The lesson's steps use subList(1, nums.size - 1).
How the indexes line up
For [4, 8, 15, 16, 23] the size is 5, so the last index is 4. The slice runs from index 1 up to, but not including, index 5 - 1 = 4. That takes the items at indexes 1, 2 and 3, which are 8, 15 and 16. The length of the slice is 4 - 1 = 3, always two less than the length of the list.
Edge cases and common mistakes
- Two numbers.
subList(1, 1)is empty, which is the expected answer. - Ending at
nums.size. That keeps the last number. The end must benums.size - 1. - Starting at 0. That keeps the first number.
- Fewer than two numbers. The constraints rule it out. With a single number the call becomes
subList(1, 0), which throws anIllegalArgumentExceptionbecause the start is larger than the end.
More cases to try
Here are a few more inputs, with what the function returns for each. Try them in the editor above after the lesson's own tests pass:
| nums | result |
|---|---|
[5, 1, 5, 1] | [1, 5] |
[7, 7] | [] |
[-3, 0, 3] | [0] |
[1, 2, 3, 4] | [2, 3] |
The numbers themselves don't matter: only the positions decide what is dropped. In [5, 1, 5, 1] the 5 and 1 at the ends go, even though the same values appear in the middle. The original list is also unchanged by the call, so after taking the middle of [4, 8, 15, 16, 23] the original still holds all five numbers, and the result has size 3.
Testing
[4, 8, 15, 16, 23]gives8 15 16.[9, 0, 9]gives0.[1, 2]gives an empty list.
