Start learning free

LESSON 260 OF 414 · TWO POINTERS

Rotate Array by One in Rust: In Place, O(n)

Practice O(n) Read the full explanation

Given an array of integers nums, rotate it in-place by one position to its right.

Do not allocate extra space for another array. You must do this by modifying directly the input array with O(1) auxiliary space.


Example 1:

Input: nums = [1, 2, 3, 4, 5]
Output: [5, 1, 2, 3, 4]

Example 2:

Input: nums = [4, -2, 13, 1]
Output: [1, 4, -2, 13]

Note:

Your algorithm should run in O(n) time and use O(1) auxiliary space.


STEP 1 OF 4
    Ctrl + Enter to check

    RUST · TWO POINTERS

    Rotate Array 1 in Rust, explained

    Problem overview

    The function rotate receives nums: &mut Vec<i32> and rotates it one position to the right, in place. Every element moves one slot to the right and the last element wraps around to the front. It returns nothing; the caller sees the change in its own vector. For [1, 2, 3, 4, 5] the vector becomes [5, 1, 2, 3, 4], and [4, -2, 13, 1] becomes [1, 4, -2, 13].

    The statement asks for O(n) time and O(1) auxiliary space, so building a second vector is not allowed.

    Approach: save the last element, shift, then place it

    Each element except the last moves to the next index, and the last one ends up at index 0. Shifting everything right would overwrite the last element, so it is saved first in a variable.

    The order of the shifts matters. Copying left to right, with nums[i] = nums[i - 1] for increasing i, would copy the first value into every slot, because each assignment reads a slot that the previous step has just overwritten. Going right to left reads every slot before it is overwritten. Slot 4 gets the value of slot 3, then slot 3 gets slot 2, and so on.

    On [1, 2, 3, 4, 5], with 5 saved, the vector goes through [1, 2, 3, 4, 4], [1, 2, 3, 3, 4], [1, 2, 2, 3, 4] and [1, 1, 2, 3, 4]. The last step puts the saved 5 at index 0 and gives [5, 1, 2, 3, 4].

    Step by step

    1. Save the end. Declare n as nums.len() and last as nums[n - 1]. This copies the number out, so it stays safe while the slots are overwritten.
    2. Shift right to left. Loop with for i in (1..n).rev(). The range 1..n excludes n, and .rev() walks it backwards, from n - 1 down to 1.
    3. Copy one slot over. Inside the loop, nums[i] = nums[i - 1];. Each element ends up one slot further right.
    4. Place the saved element. After the loop, nums[0] = last;. The loop's last iteration has already copied the old first element to index 1, so index 0 is free.

    The solution in Rust

    impl Solution {
        fn rotate(nums: &mut Vec<i32>) {
            let n = nums.len();
            let last = nums[n - 1];
            for i in (1..n).rev() {
                nums[i] = nums[i - 1];
            }
            nums[0] = last;
        }
    }
    

    Rust details worth knowing:

    • The parentheses in (1..n).rev() are required. Written as 1..n.rev(), the method call binds to n only, and the compiler rejects it because an integer has no rev method.
    • &mut Vec<i32>. The function borrows the caller's vector mutably, so assignments such as nums[i] = ... change the caller's data. There is no return value, and the function can't keep the vector after it returns.
    • Reading and writing in one statement. nums[i] = nums[i - 1] compiles because an i32 is Copy: the right side is read out as a plain number before the assignment happens.
    • Library alternative. The standard library has nums.rotate_right(1), which does the same job. The loop is what that call does, written out.

    Complexity

    Time: O(n). The loop runs n - 1 times with constant work each.

    Space: O(1). The only extra values are n, last and the loop variable.

    Edge cases and common mistakes

    • One element. [7] stays [7]. The range 1..1 is empty, and the last step writes the element onto itself.
    • Two elements. [1, 2] becomes [2, 1].
    • Empty vector. nums[n - 1] fails. In an optimized build, 0 minus 1 wraps to the largest usize, and the index panics with "index out of bounds: the len is 0". In a debug build the subtraction itself panics. A guard that returns early when the vector is empty fixes it.
    • Looping left to right. for i in 1..n { nums[i] = nums[i - 1]; } turns [1, 2, 3, 4, 5] into [1, 1, 1, 1, 1]. Always read before you overwrite.
    • Forgetting to save the last element. It is the one value the loop never copies anywhere, so it would be lost.

    Testing

    • [1, 2, 3, 4, 5] becomes [5, 1, 2, 3, 4].
    • [4, -2, 13, 1] becomes [1, 4, -2, 13].
    • [1, 2] becomes [2, 1].
    • [7] stays [7].
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free