原始问题:
给你一个数组,找出数组中 每个数左边离它最近的 比它大的数 和右边离它最近的 比它大的数
要求算法复杂度:O(N)
例子:
一个数组:
对于0位置,其左面的 离它最近的 比自己大的数,没有
其右面的 离它最近的 比自己大的数 5
前四个位置的数,每个数左边离它最近的 比它大的数 和右边离它最近的 比它大的数 总结如下:
暴力解:
遍历到某个位置的时候,左边遍历找 刚刚 比其大的值,然后右边遍历找 刚刚 比其大的值。
但是复杂度O(N²)??
优化解:
准备一个栈,
栈:先进后出(像压子弹一样)
要求每次元素进栈后要维持栈中从栈底到栈顶元素值是从大到小排列的约定。将数组中的元素依次进栈,如果某次元素进栈后会违反了上述的约定(即该进栈元素比栈顶元素大),就先弹出栈顶元素,并记录该栈顶元素的信息:
即,类似于双端队列
例子:
02.32.07
当下一个3位置上的数6,大于栈中所有的数
所以,2位置上 右面最大的数 是6
2位置上 左面最大的数 是1位置上的数 4
当此数无法落在当前栈顶,当前栈顶要弹出的时候,开始生成
谁让它弹出,谁就是右边 比它大的数!
即,弹出3时,生成
下一步,弹出4时,生成:
下一步,弹出5时,生成:
(5下面没有数)
在弹出数 的过程中,生成了这些信息:
此时,栈中元素:
继续,
后续加入以下两个数,
此时栈中元素:
此时单独处理这个栈,依次弹出其中每个元素
此时,3 不是因为 任何元素的出现 而弹出的
而是因为遍历完了,不得不弹出
所以,右面比它大的 为空,左面比它大的 为下一个数5
弹出3以后,
特别注意:此时,5上面已经没有数了,所以其 右面比它大的数,为空!
弹出5后,
6中左右均无比它大的值!
总结:
该元素左边离它最近的比它大的是 该元素出栈后的栈顶元素,如果出栈后栈空,那么该元素左边没有比它大的数
该元素右边离它最近的比它大的数是 使其弹出栈的数
如果整个数组遍历完了,栈中元素单独弹出,但是此时,弹出的所有的数,都没有右边比它大的数!而左边比它大的数,就是其栈中下一个数。
如果一个数既没有因为一个数弹出,在栈中也没有下一个数,那其左右两边,不存在比它大的数。
特殊情况:
数组中的数,相等
压入栈的时候,下标压在一起:
此时,6进入后,0,1位置的数,一起结算。
下一个例子:
此时,5压入。
3压入:
此时,6进入,
0-2 一起弹出,共同结算