Skip to content

Beginner: foundations · Arrays and strings · topic 6 of 61 · 35 min

Arrays: traversal and in-place updates

Explanation

An array keeps items side by side in memory, so reading any position is O(1), but inserting or deleting in the middle shifts the rest, O(n). Most array problems are solved by walking through the array in a smart order. Reversing, rotating by k and moving zeros to the end can all be done in place with O(1) extra space.

What an array really is

An array is a row of equal-sized boxes placed next to each other in memory. Each box has a number, its index, starting at 0. Because the boxes are side by side and the same size, the computer finds box i with one calculation: start address + i × box size. That is why reading or writing nums[i] is O(1), whether the array has 10 items or 10 million.

A Python list is a dynamic array. Its boxes hold references (pointers) to the actual objects, so items of different types can share one list, but the costs are the same as a plain array: O(1) to index, O(1) amortised to append at the end.

Think of it like this: Think of numbered lockers in a long row at a railway station. To reach locker 57 you walk straight to it; you do not open lockers 0 to 56. But if a new locker must be squeezed in at position 3, every locker from 3 onwards has to move one place to the right.

Insert and delete in the middle cost O(n)

Inserting at index i means moving every item after i one place right to make room; deleting means moving them one place left to close the gap. In the worst case (index 0) that is all n items, so insert and delete in the middle are O(n). At the end there is nothing to move, so append and pop() are cheap.

Traversal patterns

  • Forward: for i in range(len(nums)), or for x in nums when you do not need the index.
  • Backward: for i in range(len(nums) - 1, -1, -1).
  • With index and value: for i, x in enumerate(nums).
  • Neighbours: for i in range(1, len(nums)) and compare nums[i - 1] with nums[i].
  • Two ends towards the middle: left = 0, right = len(nums) - 1, move them inwards (used for reversing; more in Module 3).
  • A read pointer and a write pointer: read every item, but write only the ones you keep (used for moving zeros).

Rotating by k

Rotating right by k moves every item k places to the right, and items that fall off the end come back at the front. [1, 2, 3, 4, 5, 6, 7] rotated right by 3 is [5, 6, 7, 1, 2, 3, 4]. Rotating by n (the length) gives the same list back, so always reduce k first with k % n. Do this only when n > 0, because % 0 raises ZeroDivisionError.

The easy way builds a new list with slices: nums[-k:] + nums[:-k], O(n) time and O(n) extra space. Careful: when k is 0, nums[-0:] is the whole list, so check k == 0 separately or use nums[n - k:] + nums[:n - k].

The in-place trick uses three reversals and O(1) extra space: reverse the whole list, then reverse the first k items, then reverse the rest.

python
def reverse(nums, left, right):
    while left < right:
        nums[left], nums[right] = nums[right], nums[left]
        left += 1
        right -= 1

def rotate_in_place(nums, k):
    n = len(nums)
    if n == 0:
        return
    k %= n
    reverse(nums, 0, n - 1)      # [7, 6, 5, 4, 3, 2, 1]
    reverse(nums, 0, k - 1)      # [5, 6, 7, 4, 3, 2, 1]
    reverse(nums, k, n - 1)      # [5, 6, 7, 1, 2, 3, 4]

a = [1, 2, 3, 4, 5, 6, 7]
rotate_in_place(a, 3)
print(a)   # Output: [5, 6, 7, 1, 2, 3, 4]
Each item is swapped at most twice: O(n) time, O(1) extra space.

Moving zeros to the end, keeping order

To move all zeros to the end while keeping the other items in their original order, use a write index. Walk through the list; each time you see a non-zero, copy it to position write and move write forward. When the walk ends, fill the rest of the list with zeros. That is O(n) time and O(1) extra space.

python
def move_zeros(nums):
    write = 0
    for x in nums:
        if x != 0:
            nums[write] = x
            write += 1
    for i in range(write, len(nums)):
        nums[i] = 0

a = [0, 1, 0, 3, 12]
move_zeros(a)
print(a)   # Output: [1, 3, 12, 0, 0]

Common mistakes

  • Removing items from a list while looping over it with for x in nums: the loop skips the item after each removal. Fix: build a new list, or use the write-pointer pattern.
  • Forgetting k % n, or computing it when the list is empty. Fix: if not nums: return first, then k %= len(nums).
  • Rebinding instead of changing in place: nums = nums[-k:] + nums[:-k] inside a function does not change the caller's list. Fix: assign nums[:] = … or swap items by index.
  • Off-by-one errors with range(). Fix: range(a, b) stops BEFORE b; test with a one-item list.
  • Not saying whether you return a new list or change the input. Fix: state it before coding; interviewers care.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Arrays: traversal and in-place updates · 1/8

Arrays

This lesson is about arrays: how they sit in memory, what each operation costs, and how to update them in place.

Prefer a video by a teacher? Find free videos on “array rotate by k reverse trick move zeroes in place explained” on YouTube ↗

In real life: A delivery app's rotating banner

A food delivery app shows offers in a carousel that moves one place each time you swipe. The offers are stored in an array, and the screen shows them starting from a "current" index that moves with each swipe, wrapping around with % n. Rotating the stored list itself would cost O(n) per swipe; moving one index costs O(1). Reading any offer by index stays O(1) because the array keeps items side by side.

python
offers = ["20% off", "Free delivery", "Buy 1 get 1", "Rs 50 cashback"]
start = 0
for swipe in range(5):
    print(offers[start])
    start = (start + 1) % len(offers)
Shows the four offers in order and then wraps back to "20% off".

Practice (0/4 done)

Task 1 · Code · Python

Write rotate_right(nums, k) that RETURNS A NEW LIST: nums rotated right by k places (k ≥ 0). Do not change nums. Example: rotate_right([1, 2, 3, 4, 5], 2) returns [4, 5, 1, 2, 3]. k can be larger than the length, and the list can be empty.

Task 2 · Code · Python

Write rotate_in_place(nums, k) that rotates nums right by k places IN PLACE with O(1) extra space and returns None. Use the three-reversal trick (no slicing, no new list). Example: [1, 2, 3, 4, 5, 6, 7] with k = 3 becomes [5, 6, 7, 1, 2, 3, 4].

Task 3 · Code · Python

Write move_zeros(nums) that moves every 0 to the end of nums IN PLACE, keeping the order of the other numbers, and returns None. O(n) time, O(1) extra space. Example: [0, 1, 0, 3, 12] becomes [1, 3, 12, 0, 0].

Task 4 · Code · Python

Write second_largest(nums) that returns the largest value that is STRICTLY smaller than the maximum. If there is no such value (empty list, one item, or all items equal), return None. Use one pass, O(n) time, and no sorting. Example: second_largest([3, 1, 4, 1, 5]) returns 4.

Quick quiz

Question 1

1.Why is reading nums[i] O(1) in an array?

Question 2

2.What does inserting at index 0 of a list of n items cost?

Question 3

3.Rotating a list of 5 items right by 12 is the same as rotating by…

Question 4

4.What is the extra space of the three-reversal rotation?

Question 5

5.What goes wrong when you remove items from a list inside "for x in nums"?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Why is reading nums[i] O(1) in an array?

Answer: Its position is start + i × size, one calculation

Items sit side by side and have the same size, so the address of item i is computed directly.

What does inserting at index 0 of a list of n items cost?

Answer: O(n)

Every existing item must shift one place to the right.

Rotating a list of 5 items right by 12 is the same as rotating by…

Answer: 2

12 % 5 = 2. Every full 5 rotations bring the list back to where it started.

What is the extra space of the three-reversal rotation?

Answer: O(1)

It only swaps items using a couple of index variables.

What goes wrong when you remove items from a list inside "for x in nums"?

Answer: The loop can skip the item right after each removed one

Removing shifts items left while the loop index moves on, so the next item is skipped.

In a rotated sorted array, nums[lo] <= nums[mid]. What do you know?Related

Answer: The left half nums[lo..mid] is sorted

If the start of the range is not bigger than mid, there is no rotation point between them.

From Binary search

Why can the opposite-ends walk drop nums[left] when the sum is too small?Related

Answer: Because even with the largest value still in range, nums[right], the sum is too small

Every other partner for nums[left] is smaller than nums[right], so every pair with nums[left] is too small.

From Two pointers

n items and q range-sum queries. What is the total cost with a prefix array?Related

Answer: O(n + q)

O(n) to build once, then O(1) per query.

From Prefix sums and difference arrays

What does O(1) extra space mean?Related

Answer: The extra memory stays the same size whatever n is

A fixed number of variables, however large the input: constant extra space.

From Space complexity and amortised cost

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 4 more topics in “Arrays and strings” before its exam: Prefix sums and difference arrays, Strings: building, comparing and counting, Maximum subarray: Kadane's algorithm, 2-D arrays (matrices).
  2. Module 2 exam: Arrays and strings · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Hashing, two pointers and sliding window. 61 topics left in the course before the final exam.

← Previous: The real cost of Python and JavaScript built-ins