Start learning free

LESSON 298 OF 410 · LINKED LISTS

Remove Linked List Elements in O(n) Time Complexity using Java

Practice O(n) Read the full explanation

Given the head of a singly linked list and an integer, remove all the nodes of the linked list whose value equals that integer, and return the new head.

Example:

Input: head = [1, 2, 6, 3, 4, 5, 6], integer = 6
Output: [1, 2, 3, 4, 5]


Note:

Your algorithm should run in O(n) time and use O(1) extra space.

STEP 1 OF 8
    Ctrl + Enter to check

    JAVA · LINKED LISTS

    Remove Linked List Elements in Java, explained

    Understanding the Problem

    The core challenge of this problem is to traverse the linked list and remove nodes that match the given value without using extra space. This is a common problem in linked list manipulation, often encountered in various applications such as memory management, data filtering, and more.

    Potential pitfalls include handling the removal of nodes at the beginning of the list and ensuring that the list remains properly linked after node removal.

    Approach

    To solve this problem, we can use a single pass through the linked list, maintaining a reference to the previous node to help with node removal. Here’s a step-by-step approach:

    Naive Solution

    A naive solution would involve creating a new linked list and copying over only the nodes that do not match the given value. However, this approach uses extra space and is not optimal.

    Optimized Solution

    We can optimize the solution by modifying the linked list in place. The idea is to use two pointers: one to traverse the list and another to keep track of the last node that does not need to be removed. This way, we can adjust the pointers to skip over nodes that need to be removed.

    Algorithm

    Here’s a step-by-step breakdown of the optimized algorithm:

    1. Create a dummy node that points to the head of the list. This helps handle edge cases where the head needs to be removed.
    2. Initialize two pointers: one for the current node and one for the previous node.
    3. Traverse the list. For each node:
      • If the node’s value matches the given value, adjust the previous node’s next pointer to skip the current node.
      • Otherwise, move the previous pointer to the current node.
    4. Return the next pointer of the dummy node, which points to the new head of the list.

    Code Implementation

    class ListNode {
        int val;
        ListNode next;
        ListNode(int x) { val = x; }
    }
    
    public class Solution {
        public ListNode removeElements(ListNode head, int val) {
            // Create a dummy node that points to the head
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            
            // Initialize current and previous pointers
            ListNode current = head;
            ListNode prev = dummy;
            
            // Traverse the list
            while (current != null) {
                if (current.val == val) {
                    // Skip the current node
                    prev.next = current.next;
                } else {
                    // Move the previous pointer
                    prev = current;
                }
                // Move the current pointer
                current = current.next;
            }
            
            // Return the new head
            return dummy.next;
        }
    }
    

    Complexity Analysis

    The time complexity of this approach is O(n), where n is the number of nodes in the linked list. This is because we traverse the list once. The space complexity is O(1) since we are not using any extra space other than a few pointers.

    Edge Cases

    Potential edge cases include:

    • The list is empty (head is null).
    • All nodes in the list need to be removed.
    • No nodes in the list need to be removed.
    • The head node needs to be removed.

    Each of these cases is handled by the algorithm as it uses a dummy node and adjusts pointers accordingly.

    Testing

    To test the solution comprehensively, consider the following test cases:

    • Empty list: head = [], val = 1
    • All nodes to be removed: head = [1, 1, 1], val = 1
    • No nodes to be removed: head = [1, 2, 3], val = 4
    • Head node to be removed: head = [1, 2, 3], val = 1

    Use a testing framework like JUnit to automate these tests.

    Thinking and Problem-Solving Tips

    When approaching linked list problems, always consider edge cases and think about how to handle node removal and pointer adjustments. Practice by solving similar problems and studying different algorithms for linked list manipulation.

    Conclusion

    In this blog post, we discussed how to remove elements from a linked list in O(n) time complexity using Java. We covered the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for mastering linked list manipulation and improving problem-solving skills.

    Additional Resources

    Keep going with JavaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free