Remove Element
Do the brute force, but let the front of nums itself be the kept array. read walks over every element. write is the size of the kept part, which is also the next free slot. When nums[read] should stay, copy it to nums[write] and move write forward. When it is val, skip it.
The rule we keep true after every step: nums[0 β¦ writeβ1] holds exactly the kept (non-val) elements we have seen so far, and nothing else. In simple words: everything before write is already the final answer.
Problem
You are given an integer array nums and a number val.
Remove every copy of val from nums in place β you may not create a second array to return. Then return k, the number of elements that are not equal to val.
After your function runs, the first k slots of nums must hold exactly those kept elements. Their order does not matter, and whatever is left after slot k β 1 is ignored.
An integer array nums and an integer val.
An integer k. The judge also checks that nums[0 β¦ kβ1] holds the elements that are not val (in any order).
The two 3s are removed. The first 2 slots hold the two 2s. The _ slots can be anything.
Five elements are not 2. They fill the first 5 slots, in any order.
- β’ 0 β€ nums.length β€ 100
- β’ 0 β€ nums[i] β€ 50
- β’ 0 β€ val β€ 100
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck β each hint is counted.
- 1.
What does the judge actually look at after my function returns β the whole array, or only part of it?
- 2.
If I were allowed a second array, how would I solve it? What stops me from doing that here?
- 3.
When I keep an element, which slot should it go into?
- 4.
Can writing a kept element ever destroy an element I have not looked at yet?
- 5.
Does the order of the kept elements matter?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Copy the kept elements into an extra array, then copy them back | O(N) | O(N) |
| Optimal | read visits every element; write marks where the next kept element goes | O(N) | O(1) |
Why does this belong to this pattern?
- βremove β¦ in placeβNo second array β we must reuse the front of `nums` as the output.
- βreturn k, the first k elements are checkedβThe answer is a prefix `nums[0 β¦ kβ1]` β a `write` pointer that marks the end of that prefix.
- βkeep elements that are not valβA simple keep/skip decision per element β a `read` pointer that visits each one once.
This is the anchor of the read / write family. Both pointers start at 0 and move the same way (left to right). read moves every step; write moves only when we keep something. The keep rule here is the simplest possible: "is it not val?". The next questions keep exactly the same loop and only change that rule β "differs from the last written element" (Remove Duplicates), "is non-zero" (Move Zeroes), "differs from the element two slots back" (Remove Duplicates II).
Don't make this mistake
Two pointers does not always mean one at each end. Here both pointers start at 0 and walk right together β that is the read / write sub-pattern. (A swap-from-the-end version of this problem does exist and is also O(N), but it scrambles the order and is harder to get right. The read / write loop is the one that carries over to the next four questions.)
There is no contiguous range we are measuring. The kept elements can be far apart in the input ([0, 1, _, _, 3, 0, 4, _]). We are filtering the array, not looking at a window. Nothing is ever "removed from the left" β write only moves forward.
Each erase shifts everything after it, so the loop is O(NΒ²). Worse, after an erase the next element slides into index i and then i++ skips it β [2, 2] with val = 2 leaves one 2 behind.
We never shrink nums β the old values after slot k β 1 are still there. The answer is how many we kept, which is exactly write.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Two Pointers translate into production architectures and low-level memory mechanics.
Circular Buffer & Ring Queue
Two pointer read/write head synchronization in production memory pools.
Pointers vs References Deep Dive
Pointer arithmetic, dereferencing semantics, and memory layout behind in-place array passes.
const Correctness & East-Const
Passing read-only spans with const int* without copying buffers.