Editorial
Core insight
Remove Element · Two Pointers
Core Insight for Remove Element
The key intuition for the optimal LeetCode 27 solution is to decouple the process of finding elements from the process of keeping elements.
In the brute force approach, the inefficiency stems from shifting elements repeatedly. However, we don't actually need to "delete" the bad elements; we only need to ensure the good elements end up at the front of the array.
We can maintain a Writer Pointer (often called slow or k) that points to the position where the next valid element should be placed. Simultaneously, a Reader Pointer (loop iterator) scans the array.
The Invariant:
At any point in the execution, the subarray nums[0...writer-1] contains all the values found so far that are not equal to val.
Visual Description:
Imagine the array as a single lane of memory. The reader pointer moves forward one step at a time, examining every number.
- If the
readersees a value equal toval, it ignores it (effectively "removing" it by not saving it). - If the
readersees a value not equal toval, it copies that value to the location indicated by thewriterpointer, and then thewriteradvances.
This ensures that valid elements are packed tightly at the beginning of the array, while the "garbage" or redundant data is left in the unvisited or overwritten section beyond the writer.

Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 27: Remove Element Solution & Explanation
Problem Overview
TL;DR: Use a "writer" pointer to build the valid array in the front, while a "reader" pointer scans the input, effectively overwriting unwanted values.
The LeetCode 27 problem, Remove Element, asks us to filter an integer array nums by removing all occurrences of a specific value val. Crucially, this operation must be performed in-place, meaning we cannot allocate a new array to store the result. We must modify the existing array such that the first k elements are the values that do not equal val. The function then returns k, the count of valid elements. The order of the remaining elements does not matter.
This is a classic interview question that tests a candidate's ability to manipulate memory references and array indices efficiently.
Brute Force Approach for Remove Element
The most intuitive way to solve Remove Element without knowledge of specific patterns is to mimic how a human might physically remove an item from a list. When we encounter the value val, we remove it and shift all subsequent elements one position to the left to fill the gap.
Naive Algorithm:
- Iterate through the array.
- If
nums[i]equalsval:- Shift every element from
i + 1to the end of the array one step to the left. - Decrease the array length variable.
- Decrement the iterator
iso that we re-check the current position (since a new value has shifted into it).
- Shift every element from
Pseudo-code:
k = length of nums
i = 0
while i < k:
if nums[i] == val:
for j from i to k - 2:
nums[j] = nums[j + 1]
k = k - 1
else:
i = i + 1
return kTime Complexity: . In the worst case (e.g., removing all elements), for every element we remove, we perform a shift operation that touches the remaining elements. Why it fails: While this might pass on very small constraints (), it is fundamentally inefficient. In a serious interview setting, an solution for a linear array problem is generally considered a failure because it does not utilize the available structural properties of the array.
Algorithm Strategy: Two Pointer Patterns
-
Initialize Pointers:
- Initialize an integer
writerto 0. This tracks the index where the next non-valelement will be written. - The
readerwill be the loop variable iterating from 0 tonums.length - 1.
- Initialize an integer
-
Iterate and Filter:
- Start a loop where
readertraverses the array. - Check the condition:
if (nums[reader] != val).
- Start a loop where
-
Update In-Place:
- If the condition is met (the value is valid), assign
nums[writer] = nums[reader]. - Increment
writerby 1. - (Note: If
readerandwriterare at the same index, this assignment effectively does nothing, which is fine. If they are different, it overwrites an old or invalid value).
- If the condition is met (the value is valid), assign
-
Skip Invalid Values:
- If
nums[reader] == val, do nothing. Thereaderadvances, but thewriterstays put. This effectively skips the unwanted value.
- If
-
Return Result:
- After the loop finishes, return
writer. This value represents the number of valid elements and the new logical length of the array.
- After the loop finishes, return
Execution Flow
Let's trace the algorithm with nums = [3, 2, 2, 3] and val = 3.
- Start:
writer = 0,reader = 0. - Iteration 1 (
reader= 0):nums[0]is 3.3 == val. Condition3 != 3is False.- Action: Skip.
writerremains 0.
- Iteration 2 (
reader= 1):nums[1]is 2.2 != val. Condition2 != 3is True.- Action:
nums[writer] = nums[reader]nums[0] = 2. - Increment
writerto 1. - Array State:
[2, 2, 2, 3](Note: the 2 at index 1 is copied to index 0).
- Iteration 3 (
reader= 2):nums[2]is 2.2 != val. Condition2 != 3is True.- Action:
nums[writer] = nums[reader]nums[1] = 2. - Increment
writerto 2. - Array State:
[2, 2, 2, 3].
- Iteration 4 (
reader= 3):nums[3]is 3.3 == val. Condition3 != 3is False.- Action: Skip.
writerremains 2.
- End: Loop finishes. Return
writer(2).- The first 2 elements are
[2, 2]. Correct.
- The first 2 elements are
Proof of Correctness
The correctness relies on the loop invariant: "All elements in nums[0...writer-1] are valid elements found in nums[0...reader-1]."
- Initialization: Before the loop,
writeris 0. The range is empty, so the invariant holds vacuously. - Maintenance: In each step, if
nums[reader]is valid, we append it to thewriterposition and extend the valid range. Ifnums[reader]is invalid, we do not extend the valid range. - Termination: When the loop ends,
readerhas scanned the entire array. Therefore,nums[0...writer-1]contains all valid elements from the original array, preserving their relative order (though relative order is not strictly required by this problem, this specific algorithm preserves it).
Pattern Reuse Notes
The Two Pointers - In-place Array Modification pattern is highly reusable. Understanding the writer/reader logic is crucial for the following problems:
- LeetCode 26: Remove Duplicates from Sorted Array: Instead of filtering by a specific value
val, the condition checks if the current number is different from the previous unique number. - LeetCode 283: Move Zeroes: This is almost identical to Remove Element. You "remove" zeroes using the writer pointer, then fill the remainder of the array with zeroes after the loop.
- LeetCode 80: Remove Duplicates from Sorted Array II: A variation where at most two duplicates are allowed. The logic remains the same, but the condition for the
writerpointer checksnums[writer-2]. - LeetCode 75: Sort Colors: A more complex variation using three pointers to partition the array into three sections (0s, 1s, and 2s) in a single pass.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 27
1class Solution {
2public:
3 int removeElement(vector<int>& nums, int val) {
4 int writer = 0;
5
6 // Reader iterates through the entire array
7 for (int reader = 0; reader < nums.size(); reader++) {
8 // If the current element is not the target value
9 if (nums[reader] != val) {
10 // Copy it to the writer position
11 nums[writer] = nums[reader];
12 // Advance the writer
13 writer++;
14 }
15 }
16
17 // writer represents the new length of the valid array
18 return writer;
19 }
20};Java Solution for LeetCode 27
1class Solution {
2 public int removeElement(int[] nums, int val) {
3 int writer = 0;
4
5 // Reader iterates through the entire array
6 for (int reader = 0; reader < nums.length; reader++) {
7 // If the current element is not the target value
8 if (nums[reader] != val) {
9 // Copy it to the writer position
10 nums[writer] = nums[reader];
11 // Advance the writer
12 writer++;
13 }
14 }
15
16 return writer;
17 }
18}Python Solution for LeetCode 27
1class Solution:
2 def removeElement(self, nums: List[int], val: int) -> int:
3 writer = 0
4
5 # Reader iterates through the entire array
6 for reader in range(len(nums)):
7 # If the current element is not the target value
8 if nums[reader] != val:
9 # Copy it to the writer position
10 nums[writer] = nums[reader]
11 # Advance the writer
12 writer += 1
13
14 return writer