程序设计思维与实践 Week5 作业 A-最大矩形

题目链接:A-最大矩形

题目描述:
给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是2, 1, 4, 5, 1, 3, 3, 他们的宽都是1,其中最大的矩形是阴影部分。
在这里插入图片描述

Input:
输入包含多组数据。每组数据用一个整数n来表示直方图中小矩形的个数,你可以假定1 <= n <= 100000. 然后接下来n个整数h1, …, hn, 满足 0 <= hi <= 1000000000. 这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1。 测试数据以0结尾。

Output:
对于每组测试数据输出一行一个整数表示答案。

Sample Input:
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

Sample Output:
8
4000

思路:
首先考虑到对于每一个高度,按照数组顺序遍历,然后和当前的高度值比较,如果小于当前值,那么更新高度,比较面积大小,这个过程的时间复杂度时O(n^2),对于数据量较小的操作可以实现,但是考虑到1000000000的数据量,必定超时,所以就考虑到单调栈结构。如果从第一个开始查询,到第i个的时候,我们可以左向找到离i最近且小于i高度的矩形,并且不断向右扩展,直到找最大面积对应的高度。创建一个空栈,只有当栈空或着入栈元素小于栈顶元素时,弹出栈顶元素,实现一个单调递增栈的结构,在弹栈过程中不断更新最大面积和宽度。

总结:
单调栈可以减少查询的时间复杂度,将暴力求解的O(n^2)优化成了O(n),而且可以快速找到数列中某个元素左右最近的小于或大于该值的元素,只是需要改变一下单调增减或左右遍历顺序而已。

代码:

#include<iostream>
#include<stack>
#include<stdio.h>
using namespace std;
long long arr[1000010];
int main(){
	int n,ans;
	long long area;
	int width;
	stack<int> s;
	while(scanf("%d",&n)){
		if(n==0)
			break;
		area=0;
		for(int i=0;i<n;i++)
			scanf("%d",&arr[i]);
		while(!s.empty())
			s.pop();
		for(int i=0;i<n;i++){
			while(!s.empty()&&arr[i]<=arr[s.top()]){
				width=i-s.top();
				ans=s.top();
				s.pop();
				if(s.empty())
					width+=ans;
				else
					width+=ans-s.top()-1;
				area=max(area,arr[ans]*(width));
			}
			s.push(i);
		}
		printf("%d\n",area);
	}
	return 0;
}
发布了24 篇原创文章 · 获赞 0 · 访问量 508

猜你喜欢

转载自blog.csdn.net/qq_43666020/article/details/104988742
今日推荐