Problem overview
The method firstN gets an ArrayBuffer[Int] named nums and a number n. It returns a new ArrayBuffer[Int] with the first n numbers of nums, in the same order. When n is 0, the result is empty. The constraints say n is never larger than the length of nums.
For nums = [3, 8, 1, 9, 4] and n = 3, the result is [3, 8, 1]: the 9 and the 4 are left out. For nums = [5, 6, 7] and n = 0 the result is empty, and for nums = [2, 4] and n = 2 every number is kept.
Approach
This is a job for slice. nums.slice(0, n) copies the items from index 0 up to, but not including, index n, which are exactly the items at indexes 0 to n - 1: n items. No loop is needed, and no special case for 0 either, because slice(0, 0) is already an empty buffer.
Step by step
- Slice from 0 to
nand store the copy in avalnamedresult. - Return
result. It is a new buffer, sonumsitself is untouched.
Why a slice and not a loop
You could also build the answer by hand: make an empty buffer, loop n times and append nums(i) each time. That works, but it is more code and more places for a mistake with the loop bounds. slice already means "copy this range", so one call states the intent. With nums = [3, 8, 1, 9, 4], slice(0, 3) gives ArrayBuffer(3, 8, 1), while slice(0, 2) would give ArrayBuffer(3, 8) and slice(1, 3) would give ArrayBuffer(8, 1). Only the first matches the task, so the start is 0 and the end is n.
The solution in Scala
class Solution {
def firstN(nums: ArrayBuffer[Int], n: Int): ArrayBuffer[Int] = {
val result = nums.slice(0, n)
return result
}
}
A few details:
sliceon anArrayBuffergives anotherArrayBuffer, so the result matches the declared return type.- The copy is independent. If the caller changes the first item of the result, the first item of
numsstays as it was. - In Scala the last expression of a block is its value, so
return resultcould be justresult. Both work.
Edge cases and common mistakes
n = 0.slice(0, 0)is empty. Printed withprintln, it shows asArrayBuffer().nequal to the length. The slice covers everything, so the result has the same numbers asnums, in a new buffer.- Off by one.
slice(0, n - 1)returns one number too few, andslice(1, n)skips the first. The end index is excluded, sonis the right end. - A larger
n. The constraints rule it out, butslicewould not fail: for[2, 4]andn = 5it returns[2, 4].
The result is a new buffer
The task says to return a buffer with the first numbers, not to cut nums down. That is the difference between slice and a method such as remove: reading part of a buffer leaves the original alone, so a caller who still needs all of nums can keep using it after the call. If you ever need the buffer itself to shrink, that is a different job, done with remove.
Another way
Scala has a shorter name for the same job. nums.take(n) returns the first n items as a new buffer: ArrayBuffer(3, 8, 1, 9, 4).take(3) prints ArrayBuffer(3, 8, 1), and take(0) prints ArrayBuffer(). This lesson uses slice because it also handles ranges that don't start at the front.
Testing
These inputs give these results:
[3, 8, 1, 9, 4], n = 3 -> 3 8 1
[5, 6, 7], n = 0 -> (empty)
[2, 4], n = 2 -> 2 4
