定义:

单调栈,顾名思义就是说栈内的元素,按照某种方式排序下,必须是单调的。如果新入栈的元素破坏了单调性,就弹出栈内元素,知道满足单调性。

它可以很方便地求出某个数的左边或者右边第一个比它大或者小的元素,而且总时间复杂度O(N)。

起源的题目:

这道题目在网上稍微搜了下,感觉已经是泛滥了,我就拿过来再贴一遍O(∩_∩)O哈哈~

题目大意:

给出一个柱形统计图(histogram), 它的每个项目的宽度是1, 高度和具体问题有关。 现在编程求出在这个柱形图中的最大面积的长方形。

例如:

7 2 1 4 5 1 3 3

7表示柱形图有7个数据,分别是 2 1 4 5 1 3 3, 对应的柱形图如下,最后求出来的面积最大的图如右图所示。

单调栈的介绍与应用_第1张图片

看到这个题目我第一反应是,遍历每个矩形,左右寻找能扩展的最大距离,然后求面积,比较,得到结果。

太复杂,不是么?

主要是有很多重复的工作。

我是没有想到单调栈的,不过用了之后,发现代码比我想到的要好写,而且确实很容易。

 
   
   
   
   
C++语言:  高亮代码由发芽网提供
01  /*
02  * =====================================================================================
03  *       Filename:  MonotoneStack.cpp
04  *    Description:  
05  *
06  *        Version:  1.0
07  *        Created:  08/24/2012 04:37:27 PM
08  *
09  *         Author:  zhy (), [email protected]
10  * =====================================================================================
11  */
12  #include <iostream>
13  #include <stack>
14  using  namespace std;
15 
16  struct Element
17 {
18    Element( int h,  int index)
19        : height(h)
20        , startIndex(index)
21    {}
22 
23     int height; //矩形高度
24     int startIndex; //对应的索引位置
25 };
26 
27  int GetMaxRect( int rectHeights[],  int len)
28 {
29    stack<Element> s; //使用std的stack
30    s.push(Element(- 10)); //首先-1高度入栈,这样在之后的出栈策略上不会导致空栈,另外一种方法是可以在下文的while判断时加入对空栈的判断。
31     int maxArea = - 1;
32     int height = - 1;
33    
34     for (  int i= 0; i<len; ++i)
35    {
36         if (i == len) //扫描完毕时,要全部出栈,计算可能的矩形面积
37        {
38            height =  0;
39        }
40         else //扫描过程,则记录此时的矩形高度
41        {
42            height = rectHeights[i];
43        }
44 
45         while (height < s.top().height) //如果矩形高度比栈顶要小,则说明之前的矩形无法继续往右扩展,需要弹出,并计算面积
46        {
47             //计算面积的公式,核心部分
48             //根据我们的策略,新元素高度要高,则表明我们的矩形还可以继续往右扩展,因此栈内元素时满足单调性的,对此时栈内每个元素,都是可以根据自己的高度,扩展矩形到i-1的
49             int area = (i - s.top().startIndex)*s.top().height;
50            maxArea = maxArea > area ? maxArea : area;
51            s.pop();
52        }
53        s.push(Element(rectHeights[i], i));
54    }
55 
56     return maxArea;
57 }
58 
59  int main()
60 {
61     int rects[] = { 2145133};
62    cout << GetMaxRect(rects,  7) << endl;
63     return  0;
64 }

至于现在的复杂度是多少,我没想出来,欢迎告诉我微笑

参考资料:

http://blog.csdn.net/hopeztm/article/details/7868581