1、题目描述
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
2、示例
输入: [2,1,5,6,2,3]
输出: 10
3、题解
题解一:
基本思想:单调栈,单调递增栈的作用就是为了以栈顶元素为中心,向两边延伸找到小于栈顶元素的左右边界。时间复杂度O(n)空间复杂度O(n)。
- 当前heights[i]元素大于栈顶,则元素入栈,否则开始计算以栈顶元素为矩形的高往两侧延伸
- 直到遇到左右两侧第一个比这个矩形条的高度更小的矩形条,此时以栈顶元素为矩形的宽度就是该矩形最大宽度
- 寻找右边界,很明显,就是当前heights[i]元素右边界为i,如果heights[i]大于等于栈顶元素就入栈了
- 寻找左边界,显然就是栈顶下一个元素,如果栈顶没有下一个元素,说明栈顶元素是整个前i个元素最小的了,左边界就是-1
- 只要当前heights[i]元素小于栈顶元素或者i已经到底了,就计算以栈顶元素为矩形的高情况下矩形最大面积,确定左右边界
解法二:
基本思想:分治法,时间复杂度O(nlogn)空间复杂度O(n),超时。确定了最矮柱子以后,矩形的宽尽可能往两边延伸;在最矮柱子左边的最大面积矩形(子问题);在最矮柱子右边的最大面积矩形(子问题)。
解法三:
基本思想:暴力法,时间复杂度O(n^2)空间复杂度O(1)超时,两重循环分别作为矩形的左右边界遍历所有可能矩形,计算出最大面积。
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
//基本思想:单调栈,单调递增栈的作用就是为了以栈顶元素为中心,向两边延伸找到小于栈顶元素的左右边界(left,i),res = max(res, (i - left - 1) * heights[cur])
//当前heights[i]元素大于栈顶,则元素入栈,否则开始计算以栈顶元素为矩形的高往两侧延伸
//直到遇到左右两侧第一个比这个矩形条的高度更小的矩形条,此时以栈顶元素为矩形的宽度就是该矩形最大宽度
//寻找右边界,很明显,就是当前heights[i]元素右边界为i,如果heights[i]大于等于栈顶元素就入栈了
//寻找左边界,显然就是栈顶下一个元素,如果栈顶没有下一个元素,说明栈顶元素是整个前i个元素最小的了,左边界就是-1
//只要当前heights[i]元素小于栈顶元素,就计算以栈顶元素为矩形的高情况下矩形最大面积,确定左右边界
int res = 0, i, cur, left;
stack<int> st;
//遍历heights每个元素
for (i = 0; i <= heights.size(); i++)
{
//当前heights[i]元素小于栈顶元素或者当前下标已经到底了,计算以栈顶元素为矩形的高情况下矩形最大面积
while (!st.empty() && (i==heights.size() || heights[i] < heights[st.top()]))
{
cur = st.top();
st.pop();
//寻找左边界
left=!st.empty()?st.top():-1;
res = max(res, (i - left - 1) * heights[cur]);
}
st.push(i);
}
return res;
}
};
class Solution1 {
public:
int largestRectangleArea(vector<int>& heights) {
//基本思想:分治法,时间复杂度O(nlogn),超时
//确定了最矮柱子以后,矩形的宽尽可能往两边延伸
//在最矮柱子左边的最大面积矩形(子问题)
//在最矮柱子右边的最大面积矩形(子问题)
return calculateArea(heights, 0, heights.size() - 1);
}
int calculateArea(vector<int>& heights, int start, int end)
{
if (start > end)
return 0;
int lower = start;
for (int i = start; i <= end; i++)
{
if (heights[i] < heights[lower])
lower = i;
}
return max(heights[lower] * (end - start + 1), max(calculateArea(heights, start, lower - 1), calculateArea(heights, lower + 1, end)));
}
};
class Solution2 {
public:
int largestRectangleArea(vector<int>& heights) {
//基本思想:暴力法,时间复杂度O(n^2)空间复杂度O(1)超时,两重循环分别作为矩形的左右边界遍历所有可能矩形,计算出最大面积
int res = 0, i, j, k, cur, lower;
for (i = 0; i < heights.size(); i++)
{
lower = heights[i];
for (j = i; j < heights.size(); j++)
{
lower = min(lower, heights[j]);
cur = lower * (j - i + 1);
if (cur > res)
res = cur;
}
}
return res;
}
};
int main()
{
Solution solute;
vector<int> heights = { 2,1,2 };
cout << solute.largestRectangleArea(heights) << endl;
return 0;
}
本文介绍了一种计算给定柱状图中能够勾勒出的最大矩形面积的算法,通过三种方法:单调栈、分治法和暴力法进行解析,并提供了详细的代码实现。
901

被折叠的 条评论
为什么被折叠?



