Introduction
Welcome to your third lesson! In our previous session, we explored the inner workings of Python's list, understanding it as a dynamic array. We learned that while appending is an efficient amortized O(1) operation, inserting or deleting elements in the middle costs O(n) due to the need to shift subsequent elements. This performance characteristic is a critical consideration in algorithm design.
Today, we'll build on that by tackling a common constraint in coding interviews: in-place manipulation. Many problems require you to modify an array directly without allocating a new one, which means operating within O(1) auxiliary space. This constraint tests your ability to think creatively about data manipulation.
Our goal is to learn how to solve problems involving in-place array modifications. We'll do this by working through two classic examples: removing duplicates from a sorted array and rotating an array. These problems will introduce you to powerful patterns that are fundamental for your interview preparation.
1. The Essence of In-Place Algorithms
An "in-place" algorithm transforms the input data using a small, constant amount of extra memory. For arrays, this means you are expected to modify the given array itself rather than creating a new one to store the result. This is a common requirement to test for space efficiency.
Let's dive into our first problem, which is a perfect illustration of this principle.
2. Problem 1: Removing Duplicates from a Sorted Array
The Task: Given a sorted integer array nums, remove the duplicates in-place such that each unique element appears only once. The relative order of the elements must be kept the same. You should return the number of unique elements.
The key constraints here are:
- The array is sorted. This is a major hint!
- The modification must be in-place.
- The relative order of unique elements must be preserved.
Since the array is sorted, all duplicate elements will be grouped together. This structure allows us to solve the problem efficiently. The core idea is to use two pointers: one to iterate through the array (a "read" pointer) and another to keep track of the position for the next unique element (a "write" pointer).
This video provides an excellent walkthrough of this two-pointer strategy.
Remove Duplicates From Sorted Array - Leetcode 26 - Arrays & Strings (Python)
Watch this video from Greg Hogg to see how to solve the 'Remove Duplicates from Sorted Array' problem using an elegant in-place approach.
Watch the entire video (00:00 - 04:49). Pay close attention to: The roles of the two pointers, i (the scanner) and j (the writer). The condition nums[i] != nums[i-1] that identifies a new unique element. How returning j gives the correct count of unique elements.
Dissecting the Two-Pointer Logic
As the video demonstrated, the algorithm is surprisingly concise. Let's break it down:
- A write pointer (let's call it
jorwrite_index) starts at index 1 (or 0, depending on implementation style). This pointer marks the boundary of the processed, unique part of the array. The elements fromnums[0]tonums[j-1]are the unique elements found so far. - A read pointer (let's call it
i) iterates through the array from the second element. - At each step, we compare the element at the read pointer,
nums[i], with the last-known unique element,nums[j-1]. - If
nums[i]is different, it means we've found a new unique element. We then place it at the write pointer's position (nums[j] = nums[i]) and advance the write pointer (j += 1). - If
nums[i]is the same, we do nothing but advance the read pointer, effectively skipping the duplicate.
The final value of the write pointer, j, is the length of the subarray containing unique elements.

This approach is highly efficient:
- Time Complexity: O(n), because we iterate through the array once with our read pointer.
- Space Complexity: O(1), as we only use a few variables (pointers) and modify the array in-place.
To solidify your understanding and learn about common errors, the following reading is very helpful.
26. Remove Duplicates from Sorted Array - In-Depth Explanation
This article from Algo.monster provides another clear explanation and highlights common pitfalls when implementing this solution.
Read the sections 'Intuition', 'Solution Approach', and 'Common Pitfalls'. The 'Common Pitfalls' section is particularly valuable, as it shows incorrect implementations and explains why they fail. This is crucial for avoiding simple mistakes under interview pressure. Estimated time: 10 minutes.
3. Problem 2: Rotating an Array
Let's tackle another common in-place manipulation problem that requires a different kind of thinking.
The Task: Given an array, rotate the array to the right by k steps, where k is non-negative.
For example, if nums = [1, 2, 3, 4, 5, 6, 7] and k = 3, the result should be [5, 6, 7, 1, 2, 3, 4].

A simple solution would be to create a new array and place each element in its new, rotated position using modular arithmetic: new_nums[(i + k) % n] = nums[i]. This works, but it requires O(n) extra space for the new array. The real challenge is to do it in O(1) space.
There's a surprisingly elegant and clever algorithm to achieve this using reversals.
Rotate Array - Leetcode 189 - Python
This NeetCode video first explains the O(n) space solution and then walks through the brilliant O(1) space reversal technique.
Watch the video until 08:48. Focus on understanding: The straightforward O(n) space solution (00:00 - 04:06). This is a good baseline. The three-step reversal algorithm for the O(1) space solution (04:06 - 06:24). The Python implementation, including the important edge case of k being larger than the array length (06:24 - 08:48).
The Three-Reversal Algorithm
The logic, once you see it, is a fantastic trick to remember. To rotate an array to the right by k steps:
- Reverse the entire array.
[1, 2, 3, 4, 5, 6, 7]becomes[7, 6, 5, 4, 3, 2, 1]
- Reverse the first
kelements. (Fork=3)[7, 6, 5]becomes[5, 6, 7]. The array is now[5, 6, 7, 4, 3, 2, 1]
- Reverse the remaining
n-kelements.[4, 3, 2, 1]becomes[1, 2, 3, 4]. The array is now[5, 6, 7, 1, 2, 3, 4]
And just like that, the array is rotated correctly in O(1) space! Each reversal can be done in-place by swapping elements from the ends inwards.
- Time Complexity: O(n), because we pass through the elements three times (one for each reversal), which is still linear.
- Space Complexity: O(1).
For a deeper dive and to see another interesting in-place method, check out the following resource.
189. Rotate Array - Solution & Explanation
This article from NeetCode explains the reversal technique in text and also introduces an alternative O(1) space solution called 'Cyclic Traversal'. It's good to be aware of multiple approaches.
Please read the following sections: 'Using Reverse': A textual recap of the video. 'Cyclic Traversal': This presents a different in-place approach where you move elements one by one to their destination. It's slightly more complex to implement but a valid alternative. 'Common Pitfalls': Pay special attention to 'Forgetting to Handle k Greater Than Array Length' and 'Incorrect Reversal Boundaries'. Estimated time: 10 minutes.
Conclusion
In this lesson, we focused on the crucial skill of in-place array manipulation. You've seen how to modify an array directly to save space, a common requirement in performance-critical applications and technical interviews.
Key Takeaways:
- In-place algorithms operate directly on the input data, aiming for O(1) auxiliary space complexity.
- For removing duplicates from a sorted array, a two-pointer technique (with one read and one write pointer) is a highly efficient O(n) time, O(1) space solution.
- For rotating an array, the three-reversal method is a clever and efficient O(n) time, O(1) space algorithm that is a great pattern to have in your toolbox.
- Always consider edge cases, such as an empty array or rotation values (
k) larger than the array's length.
Preview of the Next Lesson
We got a preview of the two-pointer technique today. In the next lesson, we will formalize this concept. You'll learn how to apply the two-pointer technique as a general pattern to solve a wider variety of problems on sorted arrays and strings, such as finding pairs that sum to a target, or squaring a sorted array.