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 val from nums, in-place, and return the number k of elements that remain.

Important details:

  • You must modify nums in-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 k elements of nums after your function returns.
    Anything after index k - 1 can 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 nums are [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 nums directly
  • 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:

  • ifast pointer: scans every element in the array
  • kslow pointer: tracks where to write the next valid element

Intuition:

  • Start with k = 0
  • For each index i from 0 to len(nums) - 1:
    • If nums[i] is not equal to val, this element should stay in the array:
      • Write it at position k: nums[k] = nums[i]
      • Move k one step forward (k += 1)
    • If nums[i] == val, we skip it (do nothing)

At the end:

  • All elements that are not equal to val are packed into nums[0..k-1]
  • The value k is 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 i from 0 to 4.

Step 1: i = 0

  • nums[0] = 3
  • nums[0] == val → this element should be removed
  • We do nothing
  • k remains 0
  • 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
  • k stays at 2
  • 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 k elements: nums[:3] = [2, 2, 4] → these are the valid ones
  • All occurrences of 3 have 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 nums in-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 valk

Not the array itself.

The judge will:

  • Look at the first k elements of nums
  • 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 k to 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