引入 - 每日温度
首先来分析一道非常简单的题目。题目是这样的,给一个数组,对于原数组中的第i个元素,至少往右走多少步,才能遇到一个比自己大的元素(如果之后没有比自己大的元素,或者已经是最后一个元素,则在返回数组的对应位置放上0)。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
对于第0个数字73,需要走一步到达74,就可以遇到比自己大的元素。对于第6个元素,之后没有比它更大的数字,因此是0。
暴力做的结果就是O(n^2)的时间复杂度,例如对于一个单调递减的数组,每次都要走到数组的末尾。
那么用单调栈怎么做呢?
对第一个温度 73度,堆栈为空,把它的下标压入堆栈;
下一个温度 74度,高于 73 度高,因此 73 度温度升高只需 1 步,把 73 度下标从堆栈里弹出,把 74 度下标压入;
同样,从 74 度只需要 1步升高到 75 度;
71 度低于 75 度,直接把 71 度下标压入堆栈;
69 度低于 71 度,压入堆栈;
72 度高于 69 度,从 69 度升温只需 1步,从 71 度升温需要 2步;
由于堆栈里保存的是下标,能很快计算步数;
该方法只需要对数组进行一次遍历,每个元素最多被压入和弹出堆栈一次,算法复杂度是 O(n)。
看看代码:
概念
单调递增或单调递减的栈,跟单调队列差不多,但是只用到它的一端。