[toc]
# 单调栈的性质:
下面这两条很重要
- 单调栈实际上就是一个栈
- 每次新元素入栈后,单调栈内元素都保持单调 (递增或递减)
实现起来也很简单,就是标准入栈过程,只需要维护栈内的单调性就可以了 单调栈常用来解决一种典型问题:下一个最大元素
输入一个数组,返回一个等长的数组,对应索引存储着下一个更大的元素,如果没有更大的元素,就存 - 1
Leetcode
# 496,Next Greater Number
这道题 O (N^2) 就可以了
一种优化方法是,在 map 上把 nums2 给装进去,然后遍历 nums1 时二分 map 然后这道题的描述很 shit, 其实这道题说的意思不是相同下标,而是两个数组相同值的右边 就是单调栈模板
1 | class Solution { |
# 下一个更大的元素 ②
这道题没规定循环只能到自己为止
这道题本来想做一个 struct, 有下标和数据,然后拓展 vector 到二倍
但是官方题解说可以直接用单调栈只记录下标
确实,这样会省略掉很多麻烦的问题。然后是正向单调栈的方案 上一题用的是逆序插入单调栈,每次遇到的第一个大于当前元素的则一定是对的。正序插入单调栈,我们就需要维护该单调栈仍然是单调递减的,对于 pop 出来的而言,他就是第一个比他们大的。所以要在 pop 的时候赋值
1 | class Solution { |
# discuss 里的一道面试题
https://leetcode-cn.com/circle/discuss/l8Hse4/ 第 1 题 给定一个长度为 m(m >= 1)的字符串,这个字符串表示一个非负整数 N(应该可以用 long 装下,我是最后超时了)。其中 N 没有前导 0。 再给定一个整数 x(x <= m),要你从整数 N 中删除 x 个数字,使得余下的数字最小。最后输出这个最小的数字。 例如:
输入:N=2020,x = 1
输出:20
解释:删除第一个 2,剩下 020=20 输入:N=1432319,x = 3
输出:1219
先讨论性质 方法一,考虑保留哪些数
- 考虑保留那些数
方案 1:N 长度为 m,删除 x 个数字,那就剩 m-x 个数字,所以就是求原始序列 N 的长度为 m-x 的子序列,使得这个子序列最小。 以输入 N = 1432319 为例,m=7 x=3,m-x=4,所以我们的目标是要从 N 中挑出 4 个数来,这 4 个数的相对顺序是不能变的。下面是步骤:
1 | N=1432319,目标长度4,所以第1个数只能从1432里面取,不然后面的数就不够用了。这里肯定选最小的1,结果变成1 |
方案 2:上面的方案中,需要每次去找某个区间的最小值,导致时间复杂度是 O (m*x),如果想优化可以针对这个问题引入单调 (递增) 栈,单调栈这里就不介绍了,网上随便搜一下就有。具体步骤:
1 | 启动的时候先压入4个数1432,压完单调栈变成12 |
改进后时间复杂度变为 O (m),但注意这是一个变种栈,我们从栈底而不是栈顶出栈,所以栈的底层实现需要是 linkedlist,而不是 array。 这句话中的那四步非常重要,即考虑剩下 4 个,那么就只能在前面 N-4 个值中取一个最小的放到最高位上 第一位找好了,找第二位,考虑剩下 3 个,就只能在刚才选好的下标后面的子串中 不包含最后三位
中找一个最小的放到最高位上 这个过程可以用单调栈进行区间最小值的查找 这个思路非常巧妙