小记录59, 60 (完结篇)

50 阅读4分钟

503.下一个更大元素II

接上题,本题的关键是怎么“拐弯”,即我现在在数组末端,要找数组最后一个元素更大值,怎么到数组从0开始的位置去找呢?实际上有点像 dp 里处理rolling array 的时候,怎么在两个数组之间来回切换,我说的不是重新赋值一个新的 dp array 那种,而是仍然是二维dp,但是第一维度是2,需要来回切换的那种,这种情况下,如果要从最后一个item跳到第一个,需要的就是 i % x, x 是你想要 i 向前走多少步再从头再来,比如说我现在数组里有两个值,我想在 n = 100 的情况下,从 [0, n] 进行递归,并且不断改变两个数组里的值,那么就需要让 i % 2,这样回往复地遍历这个数组的这两个item,比如 0, 1, 2, 3。0是第一个,1是第二个,到了2就回到0了再对2取模之后。

综上所述,本题只需要在I的基础上,对i进行取n的模即可,取item,往stack里放index都是这样的

42. 接雨水

非常难想的一道题目了,毕竟HARD,通过观察法可以知道下面几点

  1. 要想存住雨水,需要一片“洼地”,也就是一块地左右两边都有比他高的,才能存住雨水。
  2. 对于只有两个板子,一个板子的情况,是无论如何都存不住雨水的。
  3. 对于遇到想等的bar,eg. [2, 1, 1, 2],计算一次即可,也就是计算 2 到 2 这两块板子一共中间可以trap多少面积的water。知道这一点之后,再来看看通过这样的规律怎么得到结果呢?

(重点)

刚刚说到,当遍历到i的时候,如果i被放入了单调栈中,则栈中元素0->n-1是递增的,再接下遍历的时候,如果遇到元素j大于top value,则需要弹出,此时:

若将弹出的元素定义为 poped, 新的栈顶元素 top, 当前遍历的元素 j,

那么可以根据定义得到,j > pop < top,也就是说现在我们可以计算一下雨水面积了。这是需要进行计算的情况,即当我们遍历到的元素大于栈顶元素的时候,则需要进行计算,否则就往stack里push就行了,那么等于呢?实际上实验一下就知道等于的情况计算出来的结果是0,因此,是不是要先pop,再push,还是直接push都可以啦,反正必须要最新的!

84.柱状图中最大的矩形

一个直观且美好的想法,把每个柱子都向外尽可能地延伸,这样对于当前遍历到的柱子i,可以算得一个最大面积,最后把从[0, n - 1]全都算一遍之后,取得并返回最大值即可。

如何实现?

  1. 怎样延伸。如果左右的柱子比当前高的话,说明可以延伸,面积可以扩大。
  2. 如何延伸

这是一个大问题...

上道题目讲到对于一个 increasing monotonic stack 而言,如果遍历到了一个大于 top 的值之后,会弹出一个元素,而弹出的这个元素就是3个值的最小值(遍历到的value,弹出元素,新的top value),此时可以计算的是 tapping water,需要累加

而这道题目需要找的是 index-i 作为基础向外延伸时候的两边的最小值,因此就得用 decreasing monotonic stack,也就是从top到bottom递减的stack,因为我们找的是比top更小的值,计算和 trapping water 差不多,只不过结果不累加,而是会决定是否更新最大值。

有亮点需要注意,因为本题即使一块板子也可以有面积,因此要想个办法计算一块板子的面积,我的方法是往数组的两端添加首位0的方法,这样用monotonic stack 也能计算一块板子了,另一点就是这样添加也解决了我的板子一直是递增的,从头到尾都没计算...