单调栈问题【含详细思路,未完】

1、直方图的最大矩形面积

问题:直方图是由排列在同一基线上的一系列矩形组成的多边形。为了简单起见,假设这些矩形的宽度相等但高度可能不同。例如,下图1给出了一个直方图,其中各个矩形的高度为3、2、5、6、1、4、4,宽度为标准1单位。当给定了一个保存所有矩形高度的数组时,如何找到其中最大的矩形。
对于给定的例子,最大矩形如图阴影部分所示: 

时间复杂度和空间复杂度:O(n)

#include<iostream>
#include<stack>
#include<vector>
#include<math.h>
using namespace std;
int maxArea(vector<int> a) {
	stack<int> stk;int cur,leftIdx,area,maxArea;
	cur=leftIdx=area=maxArea=0;
	for (int i=0; i<a.size()-1; i++) {
		while(!stk.empty() && a[i]<=a[stk.top()]) {//注意<=
			cur = stk.top();
			stk.pop();
			//cout<<"弹出cur="<<cur<<",值="<<a[cur]<<endl;
			leftIdx = stk.empty()?-1:stk.top();
			area = (i-leftIdx-1)*a[cur];
			maxArea = max(area, maxArea);
		}
		stk.push(i);
        //cout<<"压入i="<<i<<",值="<<a[i]<<endl;		
	}

	while (!stk.empty()) {
		cur = stk.top();
		stk.pop();
		leftIdx = stk.empty()?-1:stk.top();
		area = (a.size()-leftIdx-1)*a[cur];
		maxArea = max(area, maxArea);
	}
	return maxArea;
}
int main() {
    int n;cin>>n;vector<int> a(n, 0);
    for (int i=0; i<n; i++) cin>>a[i];
	int res = maxArea(a);
	cout<<res;
	return 0;
}
/*
输入如下:
7
3 2 5 6 1 4 4
输出如下:
10
*/

2、矩形的最大矩阵大小

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
依次以矩阵每一行j为底,往j-1结算每一列有多少个连续的1,将结果存在一个数组height[j]。例如以矩阵这行[1,1,1,1,1]往上几行结算,可得height[j]={3,1,3,2,2}。对于每次结算得到height[j]数组,我们可以将其看成一个直方图。如[3,1,3,2,2]可以看成直方图
第一行: height[j]={1,0,1,0,0},单调栈算出maxArea=1
第二行: height[j]={2,0,2,1,1},单调栈算出maxArea=3
第三行: height[j]={3,1,3,2,2},单调栈算出maxArea=6
第三行: height[j]={4,0,0,3,0},单调栈算出maxArea=4
综上,maxArea=6

public class MaxRectangelWith1 {
 
    public static int maxRecSize(int[][] map){
        if(map == null || map.length == 0 || map.length == 0){
            return 0;
        }
 
        int maxArea = 0;
        // 有多少列,就生成多大的长度
        int[] heights = new int[map[0].length];
        // 必须以第i行做底的情况下的直方图数组
        for(int i = 0; i < map.length; i++){
            for(int j = 0; j < map[0].length; j++){
                // 如果当前位置为0,则直接置0,否则置1
                heights[j] = map[i][j] == 0 ? 0 : heights[j] + 1;
            }
            // 得到直方图中的最大值(计算以每一行为底时的最大面积,最后取最大返回)
            maxArea = Math.max(maxRecFromBottom(heights), maxArea);
        }
    return maxArea;
    }
 
    // heights代表直方图数组,返回其中最大的长方形面积,可能包含重复值
    public static int maxRecFromBottom(int[] heights){
        if(heights == null || heights.length == 0){
            return 0;
        }
        int maxArea = 0;
        Stack<Integer> stack = new Stack<>();
        for(int i = 0; i < heights.length; i++){
            // = 相等的时候是是算错了,但最后一个会算对,所以没关系
            while(!stack.isEmpty() && heights[stack.peek()] >= heights[i]){
                int current = stack.pop();
                int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
                // 以当前heights[current]为高度的最大矩形面积
                int curArea = (i - leftLessIndex - 1) * heights[current];
                maxArea = Math.max(maxArea, curArea);
            }
            stack.push(i);
        }
        // 遍历完了,但是栈中还有元素,要单独结算,R->height.length
        while(!stack.isEmpty()){
            int current = stack.pop();
            int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
            int curArea = (heights.length - leftLessIndex - 1) * heights[current];
            maxArea = Math.max(maxArea, curArea);
        }
        return maxArea;
    }
 
    public static void main(String[] args) {
        int[][] map = { { 1, 0, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 0 }};
        System.out.println(maxRecSize(map));
    }
}

3、可见山峰问题

 

 

转自:https://blog.csdn.net/pcwl1206/article/details/96841021

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值