【LeetCode84】-柱状图中最大矩形面积

方法一(暴力解法):

基本思路

在这里插入图片描述
计算矩形的面积无非就是底乘以高,但是固定底来依次计算高是不容易的,因为可以用来的底部的面积从左到右有很多中可能,所以可以尝试固定给出的几种高度值,来计算可行的底部信息。
在这里插入图片描述在这里插入图片描述

实现代码

#include <iostream>
#include <vector>
using namespace std;

class Solution {
public:
	int largestRectangleArea(vector<int>& heights) {
		int max = 0;
		for (int i = 0;i < heights.size();i++) {
			int begin=i,end=i;
			for (int j = i;j >= 0;j--) {
				if (heights[j] < heights[i])
				{
					break;
				}
				else {
					begin = j;
				}
			}
			for (int k = i;k < heights.size();k++) {
				if (heights[k] < heights[i])
				{
					break;
				}
				else {
					end = k;
				}
			}
			if (heights[i] * (end - begin + 1) > max)
				max = heights[i] * (end - begin + 1);
		}
		return max;
	}
};
int main() {
	vector<int> v;
	v.push_back(2);
	Solution s;
	cout << s.largestRectangleArea(v);
	return 0;
}

提交结果及分析

在这里插入图片描述
在这里插入图片描述
虽然利用暴力解法可以得到正确结果,但是会出现超时的问题


方法二:

实现思路

数据结构:栈

  • 栈里面维护的是高度数组的下标
  • 栈是单调递增栈,也就是维护数据高度是依次递增的

具体的过程

  1. 首先在栈中压入-1
  2. 遍历高度数组,只要比当前高度大就向栈中压入下标,否则弹栈,直到栈顶小于当前元素或者栈为空,然后再将元素压入栈中
  3. 在弹栈的同时也要计算面积,同时适当的更新最大面积
  4. 都遍历完之后栈顶元素不为空,再接着计算面积,同时适当的更新面积

原理及举例说明

imax
-1,010

i为当前遍历的下标值,max为当前最大的面积值,栈为存储的下标值
在这里插入图片描述如图所示,当前i值为1,heights[1]<heights[0],这种情况下弹栈,类似于木桶效应,所以0的面积可以确定,面积的高为height[0],面积的底为(右侧的下标值-左侧下标值-1)注意这里面左侧指的是栈顶元素,右侧为当前i值
计算得到面积为2*(1-(-1)-1)=2*1=2
更新max值,并将i=1压入栈中

imax
-1,122

在这里插入图片描述这种情况下直接将i值压入栈中,现在考虑i为4情况,进行处理

imax
-1,1 ,2,342

在这里插入图片描述此时heights[3]的面积可以确定,为绿色区域的面积
先弹栈,然后计算面积

imax
-1,1 ,242

面积的底为(i值 - 栈顶的下标值-1)
面积=heights[3]*(4-2-1)=6
在这里插入图片描述由于此时栈顶下标为2,对应的高度值heights[2]>heights[4]
接着弹栈,然后计算面积

imax
-1,146

面积的底为(i值 - 栈顶的下标值-1)
面积=heights[2]*(4-1-1)=10

在这里插入图片描述

imax
-1,1410

此时栈顶为1,对应的heights[1]<heights[4],所以可以将4压入

imax
-1,1 ,4410

依照此规则,最后再将5压入

imax
-1,1 ,4,5410

在这里插入图片描述5是数组中最后一个元素,很明显现在栈并不为空,所以要依次弹栈计算面积
之前面积的底为(i值 - 栈顶的下标值-1),现在已经是最后一个元素了,所以可以另i值为数组的大小n=6,计算出面积同时更新max值即可(注意只有比max值大的时候才更新)

实现代码

#include <iostream>
#include <stack>
#include <algorithm>
#include <vector>
using namespace std;
class Solution {
public:
	int largestRectangleArea(vector<int>& heights) {
		int amax = 0;
		stack<int> s;
		s.push(-1);
		for (int i = 0;i < heights.size();i++) {
			while (s.top() != -1 && heights[s.top()] >= heights[i]) {
				int cur = s.top();s.pop();
				int area = (i - s.top() - 1)*heights[cur];
				amax = max(area, amax);
			}
			s.push(i);
		}
		while (s.top() != -1) {
			int cur = s.top();s.pop();
			int area = (heights.size() - s.top() - 1) * heights[cur];
			amax = max(area, amax);
		}
		return amax;
	}
};
int main() {
	vector<int> v;
	v.push_back(2);
	v.push_back(1);
	v.push_back(5);
	v.push_back(2);
	v.push_back(5);
	v.push_back(8);
	v.push_back(2);
	v.push_back(1);
	Solution s;
	cout << s.largestRectangleArea(v);
	return 0;
}

提交结果及分析

在这里插入图片描述

时间复杂度和空间复杂度均为O(n)

知识补充

在这里插入图片描述

相似题目

在这里插入图片描述

两种方法的分析

方法一的优点在于比较简单,容易想到,但缺点也是显而易见的时间复杂度偏高。
方法二是用栈这一数据结构,用空间换时间,时间复杂度为O(n)

最后的总结

我自己最开始是没有想通这道题为什么分类在栈这个标签中,看了别人的题解才知道,原来是利用了栈后进先出的计算,也就是和后进来的面积会较早的算出。所以要理解数据结构的特点,明白栈的这种是数据结构具有后进先出的特性,这样才能合理应用在解题中。
另一点就是要明白时间和空间复杂度很大程度上都是能够相互转换的,可以用空间去换时间,也可以用时间去换空间,但尽量追求二者的复杂度都不要太高。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值