Remove Nodes From Linked List
MEDIUMDescription
You are given the head of a linked list.
Remove every node which has a node with a greater value anywhere to the right side of it.
Return the head of the modified linked list.
Example 1:
Input: head = [5,2,13,3,8] Output: [13,8] Explanation: The nodes that should be removed are 5, 2 and 3. - Node 13 is to the right of node 5. - Node 13 is to the right of node 2. - Node 8 is to the right of node 3.
Example 2:
Input: head = [1,1,1,1] Output: [1,1,1,1] Explanation: Every node has value 1, so no nodes are removed.
Constraints:
- The number of the nodes in the given list is in the range
[1, 105]. 1 <= Node.val <= 105
Approaches
Checkout 4 different approaches to solve Remove Nodes From Linked List. Click on different approaches to view the approach and algorithm in detail.
Brute Force with Nested Loops
This approach uses a straightforward, brute-force method. It iterates through each node of the linked list, and for each node, it performs a second scan through all the subsequent nodes to check if there exists any node with a strictly greater value. If a greater value is found, the current node is removed from the list.
Algorithm
- Create a
dummynode that points to theheadto simplify edge cases like removing the original head. - Use two pointers,
prevandcurrent.prevwill point to the last node that was kept, andcurrentwill iterate through the list. - For each
currentnode, start another pointerrunnerfromcurrent.next. - Iterate with
runnerthrough the rest of the list. If anyrunner.val > current.val, it meanscurrentmust be removed. - If
currentneeds to be removed, updateprev.nextto point tocurrent.next, effectively skippingcurrent. - If
currentdoes not need to be removed (i.e., the inner loop finishes without finding a greater value), thencurrentis a valid node in the final list, so we updateprevtocurrent. - Advance
currentto the next node in the list and repeat the process. - Finally, return
dummy.nextwhich points to the head of the modified list.
The core idea is to check the removal condition for each node one by one. We can use a dummy head to make the removal of the first node easier. We iterate through the list with a current pointer. For each current node, we use a runner pointer to scan the rest of the list to its right. If the runner finds any node with a value greater than current.val, we know current must be removed. To remove it, we need a pointer to the node before current, let's call it prev. We update prev.next to current.next. If the entire scan to the right of current completes without finding a greater node, we keep current and simply advance prev to current. This nested loop structure leads to a quadratic time complexity.
/**
* 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 removeNodes(ListNode head) {
ListNode dummy = new ListNode(0, head);
ListNode current = head;
ListNode prev = dummy;
while (current != null) {
boolean foundGreater = false;
ListNode runner = current.next;
while (runner != null) {
if (runner.val > current.val) {
foundGreater = true;
break;
}
runner = runner.next;
}
if (foundGreater) {
// Remove current node by linking prev to current's next
prev.next = current.next;
} else {
// Keep current node, so update prev
prev = current;
}
// Move to the next node in the original list
current = current.next;
}
return dummy.next;
}
}
Complexity Analysis
Pros and Cons
- The logic is simple and easy to understand.
- It operates in-place and uses O(1) extra space.
- The time complexity of O(N^2) is highly inefficient and will likely result in a 'Time Limit Exceeded' error for large inputs as specified in the constraints (N up to 10^5).
Code Solutions
Checking out 3 solutions in different languages for Remove Nodes From Linked List. Click on different languages to view the code.
/** * 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 removeNodes ( ListNode head ) { List < Integer > nums = new ArrayList <>(); while ( head != null ) { nums . add ( head . val ); head = head . next ; } Deque < Integer > stk = new ArrayDeque <>(); for ( int v : nums ) { while (! stk . isEmpty () && stk . peekLast () < v ) { stk . pollLast (); } stk . offerLast ( v ); } ListNode dummy = new ListNode (); head = dummy ; while (! stk . isEmpty ()) { head . next = new ListNode ( stk . pollFirst ()); head = head . next ; } return dummy . next ; } }Video Solution
Watch the video walkthrough for Remove Nodes From Linked List
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.