Remove Element

Problem

Given an integer array nums and an integer val, remove all occurrences of val in nums in-place and return the new length of the array after removal. The order of elements can be changed, and elements beyond the new length are not important.

  • 0 ≤ nums.length ≤ 100
  • 0 ≤ nums[i] ≤ 50
  • 0 ≤ val ≤ 100

Example

Input: nums = [3,2,2,3], val = 3
Output: 2

The algorithm scans through nums, skipping elements equal to val. It overwrites elements equal to val by shifting non-val elements forward. After processing, the first two elements are 2 and 2, and the returned length is 2. Elements beyond the new length are irrelevant.

Approach

Straightforward Solution

A naive approach would create a new array and copy over elements not equal to val, which uses extra space and violates the in-place constraint.

Core Observation

The problem requires removing elements equal to val in-place, which means overwriting unwanted elements with wanted ones while maintaining a valid prefix of the array.

Path to Optimal

The key insight is to use two pointers: one to read through the array and another to write the next valid element. When the read pointer encounters an element not equal to val, it writes it at the write pointer's position and increments the write pointer. This compacts all valid elements at the front of the array.

Optimal Approach

Iterate through nums with a read pointer. For each element not equal to val, copy it to the write pointer's position and increment write. After the loop, write points to the new length of the array without val elements.

Time

O(n)

The algorithm makes a single pass through the array with the read pointer, performing constant-time operations per element.

Space

O(1)

Only two integer pointers are used; no additional data structures are allocated, satisfying the in-place requirement.

Pattern Spotlight

Two Pointers (In-Place Filtering)

Use one pointer to scan all elements and another to track the position to write valid elements, effectively overwriting unwanted elements and compacting the array in a single pass.

Solution

1class Solution:
2 def removeElement(self, nums: List[int], val: int) -> int:
3
4 write = 0
5
6 for read in range(len(nums)):
7
8 if nums[read] != val:
9 nums[write] = nums[read]
10 write += 1
11
12 return write

Step-by-Step Solution

1

Traverse Array and Overwrite Non-Val Elements

4write = 0
6for read in range(len(nums)):
8 if nums[read] != val:
9 nums[write] = nums[read]
10 write += 1

Objective

To iterate through the array and overwrite elements equal to val by shifting valid elements forward.

Key Insight

By maintaining a write pointer that only advances when a non-val element is found, the algorithm compacts all valid elements at the front of the array. This avoids extra space and preserves the in-place constraint. The read pointer scans every element, ensuring no valid element is missed.

Interview Quick-Check

Core Logic

Use two pointers: read scans all elements, write tracks where to place the next valid element, enabling in-place filtering.

State & Boundaries

The write pointer always points to the next position to write a valid element, ensuring no overwriting of unprocessed elements.

Common Pitfalls & Bugs

Incrementing the write pointer unconditionally or failing to check for val leads to incorrect results or overwriting valid elements.

2

Return New Length After Removal

12return write

Objective

To return the count of elements remaining after removal of val.

Key Insight

The write pointer's final position represents the number of valid elements copied to the front of the array. Returning this value provides the new length of the array without val elements, fulfilling the problem's requirement.

Interview Quick-Check

Core Logic

Return the write pointer as the new length, since it counts how many valid elements have been placed.

Line Analysis

This solution has 2 Critical lines interviewers watch for.

Line 8 Critical
if nums[read] != val:

Check if the current element is not equal to val.

This conditional filters out unwanted elements, allowing only valid elements to be copied forward.

Line 9 Critical
nums[write] = nums[read]

Overwrite the element at the write pointer with the current valid element.

This assignment compacts the array by moving valid elements forward, overwriting elements equal to val without extra space.

Line 4 Core
write = 0

Initialize the write pointer to track the position for the next valid element.

The write pointer marks the next index where a non-val element should be placed, enabling in-place compaction of the array.

Line 12 Core
return write

Return the count of valid elements after removal.

The write pointer's final value represents the new length of the array without val elements, fulfilling the problem's contract.

Line 10 Core
write += 1

Increment the write pointer after placing a valid element.

Advancing the write pointer ensures the next valid element is placed in the correct position, maintaining a contiguous block of valid elements.

Line 6 Standard
for read in range(len(nums)):

Iterate through the array with the read pointer.

The read pointer scans every element to determine if it should be kept or removed, ensuring all elements are processed exactly once.

Test Your Understanding

Why does the write pointer only increment when a non-val element is found?

Because the write pointer marks the position to place the next valid element; incrementing it only when a valid element is found ensures that all valid elements are compacted at the front without gaps.

Related Problems

Two Pointers pattern

Don't just read it. Drill it.

Reconstruct Remove Element from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.

Unlock the Remove Element drill

or drill a free problem