題目:給定一個整型數組,數組元素隨機無序的,要求打印出所有元素右邊第一個大於該元素的值。
如數組A=[1,5,3,6,4,8,9,10] 輸出[5, 6, 6, 8, 8, 9, 10, -1]
如數組A=[8, 2, 5, 4, 3, 9, 7, 2, 5] 輸出[9, 5, 9, 9, 9, -1, -1, 5, -1]
思路1、暴力遍歷
我們很容易想到復雜度為O(n^2)的解法,遍歷數組中的每一個后面所有元素,找到第一個大於它的,輸出即可。
思路2、借助棧,時間復雜度O(n)
我們用棧來保存未找到右邊第一個比它大的元素的索引(保存索引是因為后面需要靠索引來給新數組賦值),初始時,棧里放的是第一個元素的索引值(也就是0)。
以A=[8, 2, 5, 4, 3, 9, 7, 2, 5] 舉例
1) 初始棧頂元素數組的第一個索引 0,棧頂A[stack.pop()]=A[0]=8
2) 遍歷到下一個元素值為2,它比棧頂A[stack.pop()]=A[0]=8元素值小,直接將該元素的索引入棧,棧中元素是1, 0, 棧頂A[stack.pop()]=A[1]=2
3) 遍歷到下一個元素值為5,它比棧頂A[stack.pop()]=A[1]=2元素值大,將棧頂元素出棧,並且賦值result[stack.pop()]=result[1]=5,現在棧中還剩下 0, 棧頂A[stack.pop()]=A[0]=8
接着判斷當前遍歷的元素值5是否在大於棧頂A[stack.pop()]=A[0]=8,發現小於棧頂元素,直接將該元素的索引入棧,棧中元素是2, 0, 棧頂A[stack.pop()]=A[2]=5
4) 遍歷到下一個元素值為4,它比棧頂A[stack.pop()]=A[2]=5元素值小,直接將該元素的索引入棧,棧中元素是3,2, 0, 棧頂A[stack.pop()]=A[3]=4
5) 遍歷到下一個元素值為3,它比棧頂A[stack.pop()]=A[3]=4元素值小,直接將該元素的索引入棧,棧中元素是4,3,2, 0, 棧頂A[stack.pop()]=A[4]=3
6) 遍歷到下一個元素值為9,它比棧頂A[stack.pop()]=A[4]=3元素值大,將棧頂元素出棧,並且賦值result[stack.pop()]=result[4]=9,現在棧中還剩下3, 2, 0, ....重復這個步驟,最終都因為9比棧頂元素大,棧中元素出棧,最終result[3]=9, result[2]=9, result[0]=9, 直到棧中元素都出棧了,棧為空,直接將當前元素索引值存入棧。即棧頂A[stack.pop()]=A[5]=9
7) 遍歷到下一個元素值為7,它比棧頂A[stack.pop()]=A[5]=9元素值小,直接將該元素的索引入棧,棧中元素是6,5, 棧頂A[stack.pop()]=A[6]=7
8) 遍歷到下一個元素值為2,它比棧頂A[stack.pop()]=A[6]=7元素值小,直接將該元素的索引入棧,棧中元素是7, 6,5, 棧頂A[stack.pop()]=A[7]=2
9) 遍歷到下一個元素值為5,它比棧頂A[stack.pop()]=A[7]=2元素值大,將棧頂元素出棧,並且賦值result[stack.pop()]=result[7]=5,現在棧中還剩下6, 5, 棧頂元素A[stack.pop()]=A[6]=7比當前處理的元素值5大,所以將當前元素的索引值入棧,棧中變成8, 6, 5
由於元素遍歷完了,棧中還保存的元素代表該索引處找不到右邊第一個比它大的元素值了,所以挨個將棧中元素出棧,並賦值result[8]=-1, result[6]=-1, result[5]=-1
輸出[9, 5, 9, 9, 9, -1, -1, 5, -1]
a=[8, 2, 5, 4, 3, 9, 7, 2, 5] tmp=[0]#臨時保存位置 res=[0]*len(a)#結果 i=1 while i<len(a): if len(tmp)!=0 and a[i]>a[tmp[-1]]: res[tmp.pop()]=a[i] else: tmp.append(i) i+=1 return res
相似問題:對數組中的每一個元素,找出他后面第幾個數比自己大。只需要將存放在result中的值換為index差值即可
寫在后面:(字節跳動筆試題:對於數組a,求a中每個數右邊第一個比它大的元素的索引得到數組R,同理求每個數左邊第一個比它大的元素的索引得到數組L,索引從1開始)
#求數組中每個數右邊第一個比它大的元素 a=[5,4,3,4,5] tmp=[0]#臨時保存位置 R=[0]*len(a)#結果 i=1 while i<len(a): if len(tmp)!=0 and a[i]>a[tmp[-1]]: R[tmp.pop()]=i+1 else: tmp.append(i) i+=1 #R = [0, 5, 4, 5, 0]
#求數組中每個數左邊第一個比它大的元素 a=[6,2,3,4,1] #數組翻轉(問題轉為求右邊第一個比它大的元素) a.reverse() tmp=[0]#臨時保存位置 L=[0]*len(a)#結果 i=1 while i<len(a): if len(tmp)!=0 and a[i]>a[tmp[-1]]: L[tmp.pop()]=i+1 else: tmp.append(i) i+=1 for i in range(len(L)): if L[i]!=0: L[i] = abs(L[i]-len(a))+1 #左右之間差了len(a)-1個位置 #結果翻轉得到每個數左邊第一個比它大的元素 L.reverse() #L = [0, 1, 1, 1, 4]