leetcode:84. 柱状图中最大的矩形
题目
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:
输入: [2,1,5,6,2,3]输出: 10
示例 2:![[困难] 84. 柱状图中最大的矩形 - 图2](/uploads/projects/liangduo-rjrcs@ggu4wq/f8783097de42fc25a841ff97ab42b093.jpeg)
输入: heights = [2,4]输出: 4
示例 3:
输入: heights = [2,1,2]输出: 3
解答 & 代码
单调栈(栈中存储下标,下标对应的柱子高度严格单调递增):
- 先借助单调栈,逆序遍历
heights数组,求出每根柱子右边第一根比它矮的柱子的下标,存储在rightLowerIdx - 再借助单调栈,正序遍历
heights数组,求出每根柱子左边第一根比它矮的柱子的下标,存储在leftLowerIdx - 最后再遍历
heights数组,分别以每根柱子高度heights[i]作为矩形高度,那么rightLowerIdx[i] - leftLowerIdx[i] - 1就是这个高度能向两边拓展的最大宽度,计算得到一个矩形面积curArea,如果大于全局最大矩形面积maxArea,则更新maxArea 返回
maxAreaclass Solution {public:int largestRectangleArea(vector<int>& heights) {int len = heights.size();// 1. 先借助单调栈,逆序遍历 heights 数组,求出每根柱子右边第一根比它矮的柱子的下标,// 存储在 rightLowerIdxvector<int> rightLowerIdx(len, -1);stack<int> s; // 单调栈for(int i = len - 1; i >= 0; --i){while(!s.empty() && heights[s.top()] >= heights[i])s.pop();rightLowerIdx[i] = s.empty() ? len : s.top();s.push(i);}// 2. 再借助单调栈,正序遍历 heights 数组,求出每根柱子左边第一根比它矮的柱子的下标,// 存储在 leftLowerIdxvector<int> leftLowerIdx(len, -1);while(!s.empty())s.pop();for(int i = 0; i < len; ++i){while(!s.empty() && heights[s.top()] >= heights[i])s.pop();leftLowerIdx[i] = s.empty() ? -1 : s.top();s.push(i);}// 3. 最后再遍历 heights 数组,分别以每根柱子高度 heights[i] 作为矩形高度,// 那么 rightLowerIdx[i] - leftLowerIdx[i] - 1 就是这个高度能向两边拓展的最大宽度,// 计算得到一个矩形面积 curArea,如果大于全局最大矩形面积 maxArea,则更新 maxAreaint maxArea = 0; // 柱状图中最大矩形面积for(int i = 0; i < len; ++i){int curArea = heights[i] * (rightLowerIdx[i] - leftLowerIdx[i] - 1);maxArea = max(maxArea, curArea);}return maxArea;}};
复杂度分析:设
heights数组长度为 N
- 时间复杂度 O(N):三次遍历数组
- 空间复杂度 O(N):两个数组
rightLowerIdx、leftLowerIdx长度都为 N,单调栈s中最多同时存储 N 个数
执行结果:
执行结果:通过执行用时:144 ms, 在所有 C++ 提交中击败了 12.72% 的用户内存消耗:79.4 MB, 在所有 C++ 提交中击败了 5.01% 的用户
