Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given an array of integers nums and the head of a linked list. Return the head of the modified linked list after removing all nodes from the linked list that have a value that exists in nums.
Example 1:
Input: nums = [1,2,3], head = [1,2,3,4,5]
Output: [4,5]
Explanation:
Remove the nodes with values 1, 2, and 3.
Example 2:
Input: nums = [1], head = [1,2,1,2,1,2]
Output: [2,2,2]
Explanation:
Remove the nodes with value 1.
Example 3:
Input: nums = [5], head = [1,2,3,4]
Output: [1,2,3,4]
Explanation:
No node has value 5.
Constraints:
1 <= nums.length <= 1051 <= nums[i] <= 105nums are unique.[1, 105].1 <= Node.val <= 105nums.Problem summary: You are given an array of integers nums and the head of a linked list. Return the head of the modified linked list after removing all nodes from the linked list that have a value that exists in nums.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map · Linked List
[1,2,3] [1,2,3,4,5]
[1] [1,2,1,2,1,2]
[5] [1,2,3,4]
remove-linked-list-elements)delete-node-in-a-linked-list)remove-nodes-from-linked-list)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3217: Delete Nodes From Linked List Present in Array
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode modifiedList(int[] nums, ListNode head) {
Set<Integer> s = new HashSet<>();
for (int x : nums) {
s.add(x);
}
ListNode dummy = new ListNode(0, head);
for (ListNode pre = dummy; pre.next != null;) {
if (s.contains(pre.next.val)) {
pre.next = pre.next.next;
} else {
pre = pre.next;
}
}
return dummy.next;
}
}
// Accepted solution for LeetCode #3217: Delete Nodes From Linked List Present in Array
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func modifiedList(nums []int, head *ListNode) *ListNode {
s := map[int]bool{}
for _, x := range nums {
s[x] = true
}
dummy := &ListNode{Next: head}
for pre := dummy; pre.Next != nil; {
if s[pre.Next.Val] {
pre.Next = pre.Next.Next
} else {
pre = pre.Next
}
}
return dummy.Next
}
# Accepted solution for LeetCode #3217: Delete Nodes From Linked List Present in Array
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def modifiedList(
self, nums: List[int], head: Optional[ListNode]
) -> Optional[ListNode]:
s = set(nums)
pre = dummy = ListNode(next=head)
while pre.next:
if pre.next.val in s:
pre.next = pre.next.next
else:
pre = pre.next
return dummy.next
// Accepted solution for LeetCode #3217: Delete Nodes From Linked List Present in Array
// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
// pub val: i32,
// pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
// #[inline]
// fn new(val: i32) -> Self {
// ListNode {
// next: None,
// val
// }
// }
// }
use std::collections::HashSet;
impl Solution {
pub fn modified_list(nums: Vec<i32>, head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let s: HashSet<i32> = nums.into_iter().collect();
let mut dummy = Box::new(ListNode { val: 0, next: head });
let mut pre = &mut dummy;
while let Some(ref mut node) = pre.next {
if s.contains(&node.val) {
pre.next = node.next.take();
} else {
pre = pre.next.as_mut().unwrap();
}
}
dummy.next
}
}
// Accepted solution for LeetCode #3217: Delete Nodes From Linked List Present in Array
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function modifiedList(nums: number[], head: ListNode | null): ListNode | null {
const s: Set<number> = new Set(nums);
const dummy = new ListNode(0, head);
for (let pre = dummy; pre.next; ) {
if (s.has(pre.next.val)) {
pre.next = pre.next.next;
} else {
pre = pre.next;
}
}
return dummy.next;
}
Use this to step through a reusable interview workflow for this problem.
Copy all n nodes into an array (O(n) time and space), then use array indexing for random access. Operations like reversal or middle-finding become trivial with indices, but the O(n) extra space defeats the purpose of using a linked list.
Most linked list operations traverse the list once (O(n)) and re-wire pointers in-place (O(1) extra space). The brute force often copies nodes to an array to enable random access, costing O(n) space. In-place pointer manipulation eliminates that.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Pointer updates overwrite references before they are saved.
Usually fails on: List becomes disconnected mid-operation.
Fix: Store next pointers first and use a dummy head for safer joins.