Start learning free

LESSON 121 OF 677 · ARRAYS - CHALLENGES

First N Items in Scala

Practice Read the full explanation

You get an ArrayBuffer of integers nums and a number n. Return an ArrayBuffer with the first n numbers of nums.

Keep them in the same order. When n is 0, return an empty ArrayBuffer.

 

Example 1:

Input: nums = [3, 8, 1, 9, 4], n = 3
Output: [3, 8, 1]
Explanation: The first 3 numbers are 3, 8 and 1.
The 9 and the 4 are left out.

Example 2:

Input: nums = [5, 6, 7], n = 0
Output: []
Explanation: No numbers are taken, so the result is empty.

Example 3:

Input: nums = [2, 4], n = 2
Output: [2, 4]
Explanation: n is the length of nums, so every number is kept.

 

Constraints:

  • nums has 1 to 10 numbers.
  • Every number is an integer from -1000 to 1000.
  • n is from 0 to the length of nums.
STEP 1 OF 2
    Ctrl + Enter to check

    SCALA · ARRAYS - CHALLENGES

    First N Items in Scala, explained

    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

    1. Slice from 0 to n and store the copy in a val named result.
    2. Return result. It is a new buffer, so nums itself 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:

    • slice on an ArrayBuffer gives another ArrayBuffer, 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 nums stays as it was.
    • In Scala the last expression of a block is its value, so return result could be just result. Both work.

    Edge cases and common mistakes

    • n = 0. slice(0, 0) is empty. Printed with println, it shows as ArrayBuffer().
    • n equal to the length. The slice covers everything, so the result has the same numbers as nums, in a new buffer.
    • Off by one. slice(0, n - 1) returns one number too few, and slice(1, n) skips the first. The end index is excluded, so n is the right end.
    • A larger n. The constraints rule it out, but slice would not fail: for [2, 4] and n = 5 it 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
    
    Keep going with Scala500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free