Find the bug · Easy
Fix Removing Items While Iterating
Easy Find the bug Most asked
removeNegatives(nums) removes every negative number from the list (in place) and returns it, keeping the order of the rest.
It works when negatives are spread out, but leaves some behind when two negatives are next to each other. (The Java version throws an exception instead.) Find the bug and fix it.
Example 1
Input: nums = [1, -2, 3] Output: [1, 3]
Example 2
Input: nums = [-1, -2, 3] Output: [3] Explanation: The buggy version returns [-2, 3].
The buggy code
function removeNegatives(nums) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] < 0) nums.splice(i, 1);
}
return nums;
}
function removeNegatives(nums: number[]): number[] {
for (let i = 0; i < nums.length; i++) {
if (nums[i] < 0) nums.splice(i, 1);
}
return nums;
}
def remove_negatives(nums: list[int]) -> list[int]:
for x in nums:
if x < 0:
nums.remove(x)
return nums
class Solution {
public List<Integer> removeNegatives(List<Integer> nums) {
for (Integer x : nums) {
if (x < 0) nums.remove(x);
}
return nums;
}
}
Hints
Hint 1
After removing the element at index i, which element is now at index i, and does the loop look at it?
Find and fix the bug
Loading the editor… (JavaScript is required to run code in your browser.)
Solution and explanation
Show the bug and the fix
Time O(n) · Space O(n)
The bug: removing an element shifts everything after it one position to the left, but the loop index still moves forward, so the element that slid into the current position is never checked. Two adjacent negatives: the second one survives. Python's for x in nums has the same problem internally, and Java's for-each detects the modification and throws ConcurrentModificationException.
The fix: do not mutate a list while iterating over it. Build a filtered list (filter, a list comprehension) and copy it back, iterate backwards when deleting by index, or in Java use removeIf / an explicit Iterator.remove().
Fixed version
function removeNegatives(nums) {
const kept = nums.filter((x) => x >= 0);
nums.length = 0;
nums.push(...kept); // keep the in-place contract
return nums;
}
function removeNegatives(nums: number[]): number[] {
const kept = nums.filter((x) => x >= 0);
nums.length = 0;
nums.push(...kept); // keep the in-place contract
return nums;
}
def remove_negatives(nums: list[int]) -> list[int]:
nums[:] = [x for x in nums if x >= 0] # slice assignment keeps the same list object
return nums
class Solution {
public List<Integer> removeNegatives(List<Integer> nums) {
nums.removeIf(x -> x < 0);
return nums;
}
}
Common mistakes
- Decrementing
iafterspliceworks but is easy to break later; filtering is clearer. - Removing inside the loop also makes it O(n^2), because each removal shifts the tail.
More Code Clinic: Find the Bug problems
- Fix the Binary Search · Easy
- Fix the Two Sum Hash Map · Easy
- Fix the Longest Substring Without Repeats · Medium
- Fix Merge Intervals · Medium
- Fix the Mutable Default Argument · Easy
- Fix the Substring Check · Easy