问题描述
给定一个直方图,求这个直方图中最大矩阵对应的面积是多少?
比如有个图如下 (对应的数组为:[2,1,5,6,2,3])
那么对应的最大矩形的面积应该为 10:
问题分析
这类题是很常见的一道题,也是面试当中很容易考到的一题。解决方法倒是挺多。常见的比如Divide-and-conqure
等方法,复杂度也都是O(n log n)
。
现在有没有一种更快的方法呢?复杂度可以达到 O(n)
问题求解
解法1:分治法(divide-and-conqure)
分治法,正如其名,需要对该问题分而治之。比如还是上面给定的例子:
- 分:
[2,1,5,6,2,3]
分为[2,1,5]
和[6,2,3]
分别去求解 - 合:最终的最大矩形,不是在左半直方图中,要么是在右半直方图中,或是直接跨越左右直方图。上面子问题直接对应了左半直方图中的最大矩形和右半直方图中的最大矩形。唯一剩下的就是求解第三种情况:跨越左右的直方图
针对上面跨越左右直方图的最大矩形,那么该矩形一定是跨过 [5,6]
了。那么可能的情况是 [5,6]
, [5,6,2,3]
, [2,1,5,6,2,3]
,对应的最小高度分别为5,2,1. 因此就需要:从[5,6]
出发,不断地根据最小高度扩展这个数组,并在扩展中,获得最大矩形面积即可。
代码就省略了,这个比较简单。复杂度 T(n) = 2 T(n/2) + O(n)
,因此 T(n) = O(n log n)
.
解法2:运用STL
解决2比较巧妙,思想如下:
- 1,将数组进行排序,并能获得对应的原始的下标(index)
- 2,不断地插入这些原始下标,并更新最大面积
排序后的原始下标为 [1,0,4,5,2,3]
,(分别对应原始的 [1,2,2,3,5,6]
)。
有一个辅助结构(set)用于存储不断加入的下标。先加入2个下标边界(-1和6)
step 0: (-1, 6)
step 1, 插入index 1: (-1