Beginner: foundations · Arrays and strings · topic 6 of 61 · 35 min
Arrays: traversal and in-place updates
Explanation
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.
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.
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]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.
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
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.
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)Practice (0/4 done)
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.
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].
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].
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
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Prefix sums and difference arraysArrays and strings · same module
- Strings: building, comparing and countingArrays and strings · same module
- Maximum subarray: Kadane's algorithmArrays and strings · same module
- Binary searchSorting and searching
- Two pointersHashing, two pointers and sliding window
- Linked listsStacks, queues and linked lists
Questions people ask about this
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
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.
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
- 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).
- Module 2 exam: Arrays and strings · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
- 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