雙周賽90。眼殘到不行,明明範例一和我的答案不同,還是交了出去,好冤枉的WA。即使總共吃了4個BUG,還是拿到600名,也不算太差。

題目

輸入非負整數陣列nums。對於每個nums[i],你必須找到第二個更大的數

若找不到第二個更大的數,則設為-1。
例如陣列[1,2,4,3]中,1的第二大數是4;2是3;3和4是-1。

回傳整數陣列answer,其中answer[i]是nums[i]的第二個更大的數

解法

題目要求要找到在右方、又要比當前元素大的第二個數,非常麻煩。
但是我們將元素由大到小依序加入sorted list,這樣就能確保list內元素一定比當前的還大,只剩下要找到哪些在右方。
可以將元素以其索引來表示,使用二分搜就可以找到當前元素插入位置idx,再往右一格就是要找的第二個更大的數

注意:當某個元素n出現在多個索引上,一定要等到全部處理完才能加入list中,否則二分搜會被干擾。

排序O(N log N),需要二分搜+插入list共N次,也是O(N log N)。空間複雜度O(N)。

from sortedcontainers import SortedList

class Solution:
    def secondGreaterElement(self, nums: List[int]) -> List[int]:
        N=len(nums)
        ans=[-1]*N
        
        d=defaultdict(list)
        for i,n in enumerate(nums):
            d[n].append(i)
            
        sl=SortedList()
        for k in sorted(d.keys(),reverse=True):
            for i in d[k]:
                idx=sl.bisect_left(i)+1
                if idx<len(sl):
                    ans[i]=nums[sl[idx]]
            # add all elements
            for i in d[k]:
                sl.add(i)
        
        return ans

或是先將整個nums重新排序,值較大者放前面,值同等的以索引小的優先。這樣加入相同的元素保證可以先將較左的加入sorted list,不影響二分搜結果。

from sortedcontainers import SortedList

class Solution:
    def secondGreaterElement(self, nums: List[int]) -> List[int]:
        N=len(nums)
        ans=[-1]*N
            
        sl=SortedList()
        a=[[i,n] for i,n in enumerate(nums)]
        a.sort(key=lambda x:(-x[1],x[0]))
        
        for i,_ in a:
            idx=sl.bisect_left(i)+1
            if idx<len(sl):
                ans[i]=nums[sl[idx]]
            sl.add(i)
        
        return ans