Mastering LeetCode Problem 0027
Problem 0027: Remove Element
Array questions that look simple but have in-place and O(1) space constraints are classic interview traps.
LeetCode 27 – Remove Element – is one of those fundamental problems that test whether you truly understand:
- In-place array modification
- The two-pointer pattern (fast & slow pointers)
- How to work under space constraints
In this post, we’ll walk through:
- The problem in plain English
- Why in-place modification matters
- A clean two-pointer solution
- A step-by-step walkthrough
- Time & space complexity
- Common mistakes and interview tips
1. Problem Statement in Plain English
You are given:
- An integer array
nums - An integer value
val
Your task:
Remove all occurrences of
valfromnums, in-place, and return the numberkof elements that remain.
Important details:
- You must modify
numsin-place, using O(1) extra space. - The order of the remaining elements does not matter according to the problem statement.
- The judge will only check the first
kelements ofnumsafter your function returns.
Anything after indexk - 1can be ignored.
1.1. Example
Input: nums = [3,2,2,3], val = 3
Output: 2, nums = [2,2,_,_]
k = 2- The first two elements of
numsare[2, 2]. - Values after
k(here marked_) are irrelevant.
2. Why “In-Place” Actually Matters
A very natural first idea is:
“I’ll just create a new array, copy all elements that are not
val, and return that.”
That works logically, but it violates the constraints:
- Extra space would be O(n), not O(1).
- Many interview problems (including this one) are deliberately designed to force you to think about:
- How to reuse the same array
- How to avoid extra allocations
- How to control space complexity
So we need to:
- Modify the original
numsdirectly - Avoid any additional data structures like new arrays, lists, or sets
This is where the two-pointer pattern becomes really handy.
3. Intuition: Fast & Slow Pointers
We want to filter out all elements equal to val while keeping all other elements.
Let’s use two indices:
-
i→ fast pointer: scans every element in the array -
k→ slow pointer: tracks where to write the next valid element
Intuition:
- Start with
k = 0 - For each index
ifrom0tolen(nums) - 1:- If
nums[i]is not equal toval, this element should stay in the array:- Write it at position
k:nums[k] = nums[i] - Move
kone step forward (k += 1)
- Write it at position
- If
nums[i] == val, we skip it (do nothing)
- If
At the end:
- All elements that are not equal to
valare packed intonums[0..k-1] - The value
kis the number of remaining elements
We’ve effectively compressed the array in-place, removing all occurrences of val.
4. Python Implementation (Two-Pointer Solution)
Here is a clean and optimal Python solution using your idea, polished for readability:
from typing import List
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
"""
Removes all occurrences of val from nums in-place.
Returns the number of elements that are not equal to val.
After this function:
- The first k elements of nums contain the elements != val.
- The value of k is the return value.
- Elements after index k - 1 can be ignored.
"""
# k is the "write index" (slow pointer)
k = 0
# i is the "read index" (fast pointer)
for i in range(len(nums)):
# If current element is not equal to val, keep it
if nums[i] != val:
nums[k] = nums[i]
k += 1
# k is the number of elements that are not equal to val
return k
Your original code is already correct and optimal.
I only added a docstring and some comments to make it more self-explanatory and interview-ready.
4.1. How to Call This Method
Since removeElement is an instance method, we need to create an instance of Solution:
if __name__ == "__main__":
nums = [3, 2, 2, 3, 4, 3, 5]
val = 3
sol = Solution()
k = sol.removeElement(nums, val)
print("k =", k) # number of remaining elements
print("result =", nums[:k]) # first k elements are valid
Possible output:
k = 4
result = [2, 2, 4, 5]
Everything after index k - 1 can be ignored by the judge.
5. Step-by-Step Walkthrough
Let’s walk through an example to see how the pointers move.
5.1. Example
nums = [3, 2, 2, 3, 4], val = 3
Initial state:
-
k = 0(write index) - We iterate
ifrom0to4.
Step 1: i = 0
nums[0] = 3-
nums[0] == val→ this element should be removed - We do nothing
-
kremains0 - Array:
[3, 2, 2, 3, 4]
Step 2: i = 1
nums[1] = 2-
nums[1] != val→ we want to keep this value -
Write it at position
k:nums[0] = 2 k = 1 - Array becomes:
[2, 2, 2, 3, 4]
Step 3: i = 2
nums[2] = 2- Different from
val→ keep it -
Write at
nums[k]:nums[1] = 2 k = 2 - Array:
[2, 2, 2, 3, 4](effectively the same)
Step 4: i = 3
nums[3] = 3- Equal to
val→ skip -
kstays at2 - Array unchanged:
[2, 2, 2, 3, 4]
Step 5: i = 4
nums[4] = 4-
nums[4] != val→ keep it -
Write at
nums[k]:nums[2] = 4 k = 3 - Array becomes:
[2, 2, 4, 3, 4]
End of loop:
k = 3- First
kelements:nums[:3] = [2, 2, 4]→ these are the valid ones - All occurrences of
3have been removed in-place
6. Time and Space Complexity
6.1. Time Complexity
We iterate through the array once with a simple for loop:
- Each element is visited exactly once.
- No nested loops, no recursion.
$\text{Time Complexity} = O(n)$
where ( n ) is the length of nums.
6.2. Space Complexity
We only use two integer variables:
-
k(slow pointer) -
i(fast pointer)
No additional data structures, no extra arrays.
$\text{Space Complexity} = O(1)$
This satisfies the in-place and constant extra space requirement.
7. Common Mistakes in Interviews
7.1. Using Extra Arrays or Lists
For example:
res = []
for x in nums:
if x != val:
res.append(x)
return len(res)
This breaks the problem constraint:
- Uses extra
O(n)space. - Does not modify
numsin-place.
In an interview, this is usually considered incorrect for this specific problem.
7.2. Forgetting to Return the Correct Value
The function must return:
- The number of elements not equal to
val→k
Not the array itself.
The judge will:
- Look at the first
kelements ofnums - Ignore the rest
7.3. Confusing What Needs to Be “Removed”
We are not actually deleting elements in the sense of shrinking the list length in Python.
Instead, we:
- Overwrite elements in-place
- Return
kto indicate how many leading elements are valid
Logically, “removed” means:
“Not counted and ignored beyond index
k - 1.”
7.4. Overcomplicating the Logic
Some candidates try to:
- Use multiple passes
- Shift elements one-by-one each time they see
val
This often leads to:
- Longer code
- Worse performance (e.g.,
O(n^2)in naive shifting approaches)
The two-pointer pattern keeps it:
- Simple
- Linear time
- Easy to reason about
8. Interview Takeaways
LeetCode 27 is more than just removing a value from an array:
- It’s a classic example of the fast & slow pointer pattern.
- It reinforces working under O(1) extra space constraints.
- It trains you to think in terms of:
- Filtering in-place
- Compressing arrays from left to right
Once this pattern feels natural, you’ll recognize it in many other problems:
- Remove duplicates from sorted array (LeetCode 26)
- Remove specific elements with additional rules
- Partitioning arrays based on conditions