柱状图中的最大矩形
题目描述:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
// 时间复杂度O(n^2)
class Solution {
public int largestRectangleArea(int[] heights) {
// 暴力解法
int len = heights.length;
if(len == 1) return heights[0]; // 特殊判断
int max = 0;
for(int i = 0 ; i < len ; i++){
int minHeight = heights[i];
for(int j = i ; j >= 0 ; j--){
minHeight = (minHeight>heights[j])?heights[j]:minHeight;
int sum = (i-j+1)*minHeight;
if(max < sum){
max = sum;
}
}
}
return max;
}
}
以上超时,继续优化后…
// 以下参考官方源码
class Solution {
public int largestRectangleArea(int[] heights) {
int len = heights.length;
if (len == 1) return heights[0];
int result = 0;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < len; i++) {
while (!stack.empty() && heights[i] < heights[stack.peek()]) { // 如果当前遍历下标的高度严格小于下标为栈顶的元素高度
int curHeight = heights[stack.pop()];
while (!stack.empty() && heights[stack.peek()] == curHeight) { // 相等情况下去重
stack.pop();
}
int curWidth;
if (stack.empty()) {
curWidth = i;
} else {
curWidth = i - stack.peek() - 1;
}
result = Math.max(result, curHeight * curWidth);
}
stack.push(i);
}
// 最终处理
while (!stack.empty()) {
int curHeight = heights[stack.pop()];
while (!stack.empty() && heights[stack.peek()] == curHeight) {
stack.pop();
}
int curWidth;
if (stack.empty()) {
curWidth = len;
} else {
curWidth = len - stack.peek() - 1;
}
result = Math.max(result, curHeight * curWidth);
}
return result;
}
}
空间换取时间,利用数据结构中的单调栈(所谓单调栈就是元素从栈顶到栈底按照递增或递减顺序排列的栈)来进行优化,该栈存储元素下标,如果遇到遍历的下标位置的元素大于等于栈顶中的下标对应的元素,则无法确定是否为最大的面积,遍历下标继续进栈;当遇到遍历的下标位置的元素小于栈顶中的下标对应的元素时(此时的栈一定不为空),则进行下一步处理,如此这般一直保持栈的单调性,直至遍历完整个数组。如果难以理解,请在草稿纸上模拟,其余详细具体看代码。