问题描述:
给定一个直方图,求这个直方图中最大矩阵对应的面积是多少?
例子:有个图如下 (对应的数组为:[3,2,5,6,1,4,4])
问题分析:
针对这个问题,最简单的是遍历法,复杂度O(n^2),该方法容易理解,此处着重解释下第二种:利用单调递增栈。
关于该方法的步骤,网上有很多介绍,但是把步骤看完后,还是难以理解,现在终于搞明白了。这里仅仅把自己学习中的疑难点列出来,希望能够帮助到大家更深入理解该方法。
弹出栈时面积计算:
注意栈中存储的是索引,每次数据出栈时是以出栈元素为左边界(即该索引的值为长方形的高),以待入栈元素为右边界(不包含),然后用(待入栈元素的索引-出栈元素的索引)作为长方向的宽度。
如上图,待入栈2(索引4),待出栈6(索引3),
面积( 4-3)*6=6
为何新入元素变小时要弹出前边的,直至构成递增序列:
1、若要确定长方形面积,就得确定左边界右边界。若两个边界同时变化,就是遍历法,复杂度高。
2、如果是递增序列,则右边界一定是最后一个,寻找最大面积时,只需要遍历左边界。以左边界为高,左边界和最后一个的索引差值为宽,即可计算面积。
3、但是如果新入栈的数小于前边的数,不满足递增序列,则前述的面积公式不适用。因此需要弹出前边较大的元素,直至满足递增序列。
4、此时前述面积公式仍有效,虽然前边较大的元素出去了,但是这些出去的元素构成的最大长方形的面积已经被记录下来。同时,这些出去的元素不会影响以新的右边界计算的面积(1.因为栈记录的是索引,长方形的宽只需要索引相减。2.因为弹出的元素是高于当前栈中的元素,所以新长方形的高一定是由当前栈中元素决定。)
5、实际上该方法相当于计算f(n),f(n)表示以索引n的元素为右边界的长方形的面积。