Start learning free

LESSON 155 OF 414 · LOOPING OVER ARRAY INDICES

Reverse Array in Scala: Walking the Indices Backwards

Practice Read the full explanation

Given an array of integers nums, return a list containing the integers in reverse order, without using built-in functions.

Example:

Input: nums = [2, 9, 1, 5, 8]
Output: [8, 5, 1, 9, 2]

Note:

Do not use builtin functions such as reverse(), it would defy the purpose of the challenge. Write the whole code yourself.

STEP 1 OF 4
    Ctrl + Enter to check

    SCALA · LOOPING OVER ARRAY INDICES

    Reverse Array in Scala, explained

    Problem overview

    The method reverse takes an array of integers, nums, and returns a List[Int] with the same numbers in the opposite order. For nums = [2, 9, 1, 5, 8] the result is [8, 5, 1, 9, 2]: the last element comes first and the first element comes last.

    The task rules out built-in helpers such as reverse, so you write the loop yourself.

    Approach

    To build the reversed sequence, read nums from its last index down to index 0 and add each element to a new collection. The first element added is then the last element of nums, which is exactly what the reversed order needs.

    Two choices shape the code. First, the loop has to count downwards, so a plain nums.indices won't do. Second, the result has to grow one element at a time, so you need a growable buffer rather than an array, since an array's size is fixed. At the end, the buffer becomes the List[Int] that the method promises to return.

    Step by step

    1. Create the buffer. Declare answer as an empty scala.collection.mutable.ArrayBuffer[Int](). Type parameters in Scala go in square brackets.
    2. Count down over the indices. The loop runs over nums.size - 1 to 0 by -1. The last valid index is nums.size - 1. The word to makes the range include its end, so 0 is visited, and by -1 sets the step so the range moves downward. Without by -1, a range from a larger number to a smaller one is empty.
    3. Append each element. In the body, answer += nums(i) adds the element at index i to the end of the buffer.
    4. Convert and return. After the loop, answer.toList turns the buffer into an immutable list, which matches the return type.

    Tracing the example: i takes the values 4, 3, 2, 1, 0, and the buffer grows through [8], [8, 5], [8, 5, 1], [8, 5, 1, 9] and finally [8, 5, 1, 9, 2].

    The solution in Scala

    class Solution {
        def reverse(nums: Array[Int]): List[Int] = {
            val answer = scala.collection.mutable.ArrayBuffer[Int]()
            for (i <- nums.size - 1 to 0 by -1) {
                answer += nums(i)
            }
            return answer.toList
        }
    }
    

    Scala details worth knowing:

    • Ranges. 0 until 5 gives 0, 1, 2, 3, 4 and leaves out 5. 0 to 5 includes 5. With a negative step, 4 to 0 by -1 gives 4, 3, 2, 1, 0.
    • val and a growing buffer. val answer fixes which buffer the name points to, not how many elements it holds, so += works on it.
    • Indexing with parentheses. Scala reads an element with nums(i).
    • The input is untouched. The method builds a new list and never changes nums.

    Complexity

    Time: O(n). The loop runs once for each of the n elements, and appending to an ArrayBuffer takes constant time on average. Converting to a list is one more pass over n elements, which is still O(n) in total.

    Space: O(n). The result holds n numbers, and the buffer holds the same numbers until it is converted.

    Edge cases and common mistakes

    • Empty array. The range -1 to 0 by -1 is empty, so the loop doesn't run and the result is an empty list.
    • One element. The range is just 0, and the result is the same single number.
    • Starting at nums.size. The last valid index is nums.size - 1. Starting at nums.size reads past the end and throws an ArrayIndexOutOfBoundsException.
    • Using until for the end. nums.size - 1 until 0 by -1 stops before 0 and never adds the first element, so the result is one element short.
    • Forgetting the step. nums.size - 1 to 0 counts upward by default, so for any array with more than one element the range is empty and the result is an empty list.
    • Returning the buffer. An ArrayBuffer isn't a List, so the buffer must be converted with toList.

    Testing

    • [2, 9, 1, 5, 8] gives [8, 5, 1, 9, 2].
    • [4] gives [4].
    • [] gives [].
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free