码迷,mamicode.com
首页 > 其他好文 > 详细

单调栈

时间:2015-06-03 22:55:26      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:

  单调栈是栈中的元素从栈顶到栈底单调递增或递减。单调栈只能从栈顶部添加或者删除元素,以单调递增栈为例,元素从栈顶到栈底逐渐递增,假设当前元素为e,在入栈时,从栈顶往下找,如果栈顶元素小于当前元素e,则弹出栈顶元素,直到栈顶元素小于等于该元素e,然后将e入栈;出栈时,直接弹出栈顶元素,即可得到栈中当前所有元素的最小值。

  由于每个元素都会入栈和出栈一次,因此平摊下来,时间复杂度为O(n).

单调栈示例: poj 2559 Largest Rectangle in a Histogram

  题目要求求出由给定的整数数组确定的直方图中,连续的一块最大的矩形面积,其中每个直方列的宽度均为1。

题目解法:

  将关注点放在直方图的每个列上,由该列的高度确定的一个矩形(从该点的峰点出发,分别向左和向右延伸,得到最大的宽度,从而得到由该高度确定的矩形的面积)。然后进行一次遍历,得到所有点确定的矩形中最大的一个。

   从一点向左(或右)延伸的最大长度(以向左延伸为例),就是从该点出发向左走,如果左边点的高度大于等于该点,则长度加1, 直到遇到的点的高度小于该点的高度则停止,得到最大值。这样的搜索过程,抽象出来,就是从一个序列尾部向前查找,找到合适的位置插入元素,从而形成一个递增的序列,然后从序列的尾部取出元素,这个过程可以用单调栈来实现。 在实现的时候,考虑求该点向左延伸时,左边最小的点的索引,并且将索引用栈来存储。

代码实现:注意 long long 的类型,以及 long long result = (right[i] - left[i] + 1)*hist[i]; (在hist 为整数数组时候,需要强制转换为 long long)

#include<stdio.h>
#include<stack>
#define MAX_NUM 100005
using namespace std;
int left[MAX_NUM];
int right[MAX_NUM];
int hist[MAX_NUM];
stack<int> index_stack;
void EmptyStack(stack<int> & stack){
    while(! stack.empty()){
        stack.pop();
    }
}
long long GetLargestRect(int n){
    EmptyStack(index_stack);
    for(int i = 0; i < n; i ++){
        while(! index_stack.empty() && hist[index_stack.top()] >= hist[i]){ //向左搜索,直到栈顶的元素小于当前元素
            index_stack.pop();
        }
        left[i] = i;
        if (! index_stack.empty()){
            left[i] = index_stack.top() + 1;  //得到最左的位置
        }else{
            left[i] = 0;
        }

        index_stack.push(i);
    }
    EmptyStack(index_stack);
    for(int i = n - 1; i >= 0; i --){
        while(! index_stack.empty() && hist[index_stack.top()] >= hist[i]){
            index_stack.pop();
        }
        right[i] = i;
        if (! index_stack.empty()){
            right[i] = index_stack.top() - 1;
        }else{
            right[i] = n - 1;
        }
        index_stack.push(i);
    }
    long long max_area = 0;
    for(int i =  0; i < n; i ++){
//        printf("i = %d, left(i) = %d, right(i) = %d\n", i, left[i], right[i]);

        long long result = (right[i] - left[i] + 1)*hist[i];
        if (result > max_area){
            max_area = result;
        }
    }
    return max_area;
}

int main(){
    while(true){
        int n;
        scanf("%d", &n);
        if (n == 0){
            break;
        }
        for(int i = 0; i < n; i ++){
            scanf("%d", &hist[i]);
        }
        getchar();
        long long result = GetLargestRect(n);
        printf("%lld\n", result);
    }
    return 0;
}

 

单调栈

标签:

原文地址:http://www.cnblogs.com/gtarcoder/p/4550269.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!