找出数组中每个数右边第一个比它大的元素

题目:给定一个整型数组,数组元素随机无序的,要求打印出所有元素右边第一个大于该元素的值。

如数组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]
posted @ 2020-05-07 18:42  USTC丶ZCC  阅读(2249)  评论(0编辑  收藏  举报