用法展开目录
给你一个数组,要求你找到数组中每个元素左边第一个比他大的数和右边第一个比它大的数,举个例子,数组 [3,5,2,1,6],3 左边比他大的没有,右边比他大的是 5;5 左边比它大的没有,右边比他大的是 6;2 左边比它大的是 5,右边比他大的是 6;1 左边比他大的是 2,右边比他大的是 6;6 左边比他大的没有,右边比它大的没有
单调栈应用展开目录
上面的问题,直接遍历可以,但是如果利用单调栈来做,可以保证时间复杂度为 O (n)。首先说明一下什么是单调栈,单调栈就是栈内元素都是严格单调递增或单调递减的,根据题目具体情况。
看一下单调栈的工作过程(这里是单调递减栈,就是从栈底到栈顶是递减的),还是以 nums = [3,5,2,1,6] 为例,单调栈存的是数组下标。
首先,栈空,所以下标 0 直接入栈;
然后到了下标 1,因为 nums [stack.peek ()] < nums [1],所以栈顶元素出栈,在出栈的时候记录是什么值让我出栈的,在这里是下标值 1 让栈顶出栈,所以栈顶元素的右边比他大的数的下标就是 1,然后看当前值出栈前,在栈内排在我下面的值是谁,因为 0 下面没有值,所以是空,因此 nums [0] 的左边比他大的数没有,右边比它大的数是 nums [1];
继续,因为 nums [1] > nums [2],所以 2 直接进栈;
3 也直接进栈,此时栈内从栈底到栈顶依次是 1,2,3;
然后来到了 4,因为 nums [stack.peek ()] < nums [4],所以 stack.pop (),3 出栈,出栈的时候开始记录,在栈内,3 底下的数是 2,所以 3 左边比他大的数的下标是 2,因为 4 要进栈,导致 3 出栈,所以 4 是 3 右边比它大的数的下标;
因为 nums [stack.peek ()] < nums [4],所以还要继续出栈,此时出栈的值是 2,按照之前的规则,2 左边比他大的数的下标就是 1,2 右边比它大的数的下标就是 4;
因为 nums [stack.peek ()] < nums [4],所以依然继续出栈,此时出栈的值是 1,1 左边比它大的数没有,右边比它大的数的下标是 4;
现在栈是空的,所以 4 直接进栈了,然后到了数组的边界,因此栈内剩下的所有值都直接弹出,并且按照之前的规则,记录每一个值,因为没有元素要进栈,而是便利到了数组结尾导致他们要出栈,所以栈内所有的值右边比它大的数的下标都是空,左边比它大的数的下标就是在栈内,他们下面的数。对于当前栈内情况来看,4 左边比它大的数的下标和右边比它大的数的下标都是空。