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
Solutions
Solution 1: Monotonic Stack (Array)
Thinking
Delete a node if a strictly larger value exists to its right: keep the decreasing right-to-left suffix. At \(n\le 10^5\), copy values, maintain a decreasing stack, then rebuild the list.
Store the node values in an array \(nums\), then scan \(nums\) with a monotonically decreasing stack. Pop while the current value is larger than the top, then push. Rebuild the list from the bottom of the stack.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\), where \(n\) is the length of the linked list.
1 2 3 4 5 6 7 8 910111213141516171819202122
# Definition for singly-linked list.# class ListNode:# def __init__(self, val=0, next=None):# self.val = val# self.next = nextclassSolution:defremoveNodes(self,head:Optional[ListNode])->Optional[ListNode]:nums=[]whilehead:nums.append(head.val)head=head.nextstk=[]forvinnums:whilestkandstk[-1]<v:stk.pop()stk.append(v)dummy=ListNode()head=dummyforvinstk:head.next=ListNode(v)head=head.nextreturndummy.next
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */funcremoveNodes(head*ListNode)*ListNode{nums:=[]int{}forhead!=nil{nums=append(nums,head.Val)head=head.Next}stk:=[]int{}for_,v:=rangenums{forlen(stk)>0&&stk[len(stk)-1]<v{stk=stk[:len(stk)-1]}stk=append(stk,v)}dummy:=&ListNode{}head=dummyfor_,v:=rangestk{head.Next=&ListNode{Val:v}head=head.Next}returndummy.Next}
Method 1 allocates a value array and new nodes. The same stack can hold list nodes: pop while the top is smaller, then link the new top to the current node. A dummy of \(+\infty\) avoids an empty stack.
Traverse the list directly with a monotonically decreasing stack of nodes. When the current value is larger, pop; then link the new top's \(next\) (or the dummy head) to the current node and push it. Return the dummy head's \(next\).
The time complexity is \(O(n)\), and the space complexity is \(O(n)\), where \(n\) is the length of the linked list.
1 2 3 4 5 6 7 8 91011121314151617
# Definition for singly-linked list.# class ListNode:# def __init__(self, val=0, next=None):# self.val = val# self.next = nextclassSolution:defremoveNodes(self,head:Optional[ListNode])->Optional[ListNode]:dummy=ListNode(inf,head)cur=headstk=[dummy]whilecur:whilestk[-1].val<cur.val:stk.pop()stk[-1].next=curstk.append(cur)cur=cur.nextreturndummy.next
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */funcremoveNodes(head*ListNode)*ListNode{dummy:=&ListNode{1<<30,head}stk:=[]*ListNode{dummy}forcur:=head;cur!=nil;cur=cur.Next{forstk[len(stk)-1].Val<cur.Val{stk=stk[:len(stk)-1]}stk[len(stk)-1].Next=curstk=append(stk,cur)}returndummy.Next}