Problem overview
dropEnds receives an array of integers nums with at least two numbers. It returns a new array with every number except the first and the last, keeping the order of the rest. With exactly two numbers there is nothing in between, so the result is an empty array.
For [4, 8, 15, 16, 23] the first number is 4 and the last is 23, so the answer is [8, 15, 16]. For [9, 0, 9] both 9s are ends and only [0] is left. For [1, 2] the answer is [].
Approach
Use slice with both cut points moved inwards. Starting at index 1 skips the first number. The last index of the array is nums.length - 1, and because slice stops just before its end index, using nums.length - 1 as the end leaves the last number out too. Everything between is copied in order.
Step by step
- Slice from 1 to
nums.length - 1and store the copy in a constant namedmiddleof typenumber[]. - Return
middle. With two numbers the call isslice(1, 1), which is empty, so the "two numbers" rule needs no special case.
The solution in TypeScript
class Solution {
dropEnds(nums: number[]): number[] {
const middle: number[] = nums.slice(1, nums.length - 1);
return middle;
}
}
On the three examples it returns:
[ 8, 15, 16 ] [ 0 ] []
Tracing the first example
For [4, 8, 15, 16, 23] the length is 5, so the call is slice(1, 4). Index 1 holds 8, index 2 holds 15 and index 3 holds 16, and the copy stops before index 4, which holds 23. The result has 4 - 1 = 3 items. In general the result has nums.length - 2 items, which is why two numbers give none.
The function never needs to look at the values. It works only with positions, so it behaves the same for negative numbers and for repeated numbers such as the two 9s in [9, 0, 9].
Edge cases and common mistakes
- Two numbers.
slice(1, 1)gives[], as the lesson requires. - Three numbers.
slice(1, 2)gives exactly the one number in the middle. - Using
nums.lengthas the end. That would keep the last number. The end must be one less. - Starting at 0. That would keep the first number.
- Negative indexes.
slice(1, -1)means the same thing, because a negative end counts from the back:[1, 2, 3, 4].slice(1, -1)gives[ 2, 3 ]and[1, 2].slice(1, -1)gives[]. The lesson's form withnums.length - 1spells the same cut out in plain numbers. - Removing with
shiftandpop.shiftremoves the first item andpopremoves the last, so calling both onnumsdoes produce[ 8, 15, 16 ]for the first example. But it changes the input array: after the call,numsitself is[ 8, 15, 16 ]. To use them safely, copy first withnums.slice()and remove from the copy. The lesson's singleslice(1, nums.length - 1)does the same work in one step and leavesnumsalone.
Testing
Check an even length, negative values and the largest values the constraints allow: dropEnds([5, 6, 7, 8]) returns [ 6, 7 ], dropEnds([-3, 0, 3]) returns [ 0 ] and dropEnds([1000, -1000]) returns []. In every case the answer is two items shorter than the input, never less than empty.
