周賽321。還真是我用單調堆疊最順手的一次。

題目

輸入一個linked list的首節點head。

若某節點的右方存在嚴格較大的節點,則將其刪除。

回傳修改後的首節點。

解法

直接修改節點值似乎有點算是偷吃步,但題目也沒說不行,那就當他是可行的。

每個節點的右方若有更大節點,則會被刪除;換句話說就是使得list成為遞減
維護一個單調遞減堆疊,依序遍歷所有節點,只要出現較大的節點,則把先前較小的所有節點都彈出。最後將處裡完的節點串接起來回傳。

遍歷list最多兩次,時間O(N)。最差情況下不會刪除任何節點,全部放入堆疊中,空間O(N)。

class Solution:
    def removeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
        st=[]
        curr=head
        while curr:
            while st and curr.val>st[-1].val:
                st.pop()
            st.append(curr)
            curr=curr.next
            
        for a,b in pairwise(st):
            a.next=b
        
        return st[0]

最合適的解法應該是透過遞迴,找到每個節點右方的最大值,依此判斷要不要刪除當前節點。

如果右方沒節點了,直接回傳;如果右方首節點t大於當前節點node,直接回傳t;否則將t串到node後面,回傳node。

時空間一樣都是O(N)。

class Solution:
    def removeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
        
        def f(node):
            if not node:return
            t=f(node.next)
            if not t:return node
            if t.val>node.val:return t
            node.next=t
            return node
        
        return f(head)