Taro Logo

Delete Nodes From Linked List Present in Array

Medium
Google logo
Google
1 view
Topics:
Linked ListsArrays

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:

nums = [1,2,3], head = [1,2,3,4,5]

Output: [4,5]

Remove the nodes with values 1, 2, and 3.

Example 2:

nums = [1], head = [1,2,1,2,1,2]

Output: [2,2,2]

Remove the nodes with value 1.

Example 3:

nums = [5], head = [1,2,3,4]

Output: [1,2,3,4]

No node has value 5.

Constraints:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5
  • All elements in nums are unique.
  • The number of nodes in the given list is in the range [1, 10^5].
  • 1 <= Node.val <= 10^5
  • The input is generated such that there is at least one node in the linked list that has a value not present in nums.

Solution


Naive Approach

The most straightforward way to solve this problem is to iterate through the linked list and, for each node, check if its value exists in the nums array. If it does, remove the node. This involves nested iterations, leading to a less efficient solution.

Algorithm

  1. Iterate through the linked list with a current pointer.
  2. For each node, iterate through the nums array.
  3. If current.val is found in nums, remove the node from the linked list.
  4. Continue until the end of the linked list.

Code

def remove_nodes_naive(nums, head):
    dummy = ListNode(0)
    dummy.next = head
    current = dummy

    while current.next:
        if current.next.val in nums:
            current.next = current.next.next
        else:
            current = current.next

    return dummy.next

Time and Space Complexity

  • Time Complexity: O(N * M), where N is the number of nodes in the linked list and M is the length of the nums array, due to the nested loops.
  • Space Complexity: O(1), as it uses a constant amount of extra space.

Optimal Approach

To improve efficiency, we can use a hash set (or set in Python) to store the values from the nums array. This allows for O(1) lookup time, reducing the overall time complexity.

Algorithm

  1. Convert the nums array into a hash set for quick lookups.
  2. Iterate through the linked list with a current pointer.
  3. If current.next.val is in the hash set, remove the node.
  4. Otherwise, move the current pointer to the next node.
  5. Return the modified linked list.

Code

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def remove_nodes(nums, head):
    num_set = set(nums)
    dummy = ListNode(0)
    dummy.next = head
    current = dummy

    while current.next:
        if current.next.val in num_set:
            current.next = current.next.next
        else:
            current = current.next

    return dummy.next

Time and Space Complexity

  • Time Complexity: O(N + M), where N is the number of nodes in the linked list and M is the length of the nums array. The O(M) comes from building the set. The iteration through the linked list is O(N).
  • Space Complexity: O(M), where M is the length of the nums array, due to the space used by the hash set.

Edge Cases

  • Empty Linked List: If the linked list is empty, the function should return None.
  • Empty nums Array: If the nums array is empty, no nodes should be removed, and the original linked list should be returned.
  • All Nodes Removed: If all nodes in the linked list have values present in nums, the function should return an empty linked list.
  • Head Nodes to Remove: If the head of the list should be removed, the dummy head helps handle this.

Here's the code with edge cases considered:

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def remove_nodes(nums, head):
    num_set = set(nums)
    dummy = ListNode(0)
    dummy.next = head
    current = dummy

    while current.next:
        if current.next.val in num_set:
            current.next = current.next.next
        else:
            current = current.next

    return dummy.next