LeetCode:84. 柱状图中最大的矩形 - 力扣(LeetCode)
1.思路
方法一:暴力解法。以当前节点为基准,向左右进行双向遍历,找出当前高度下的最大范围下的值,循环遍历比较得出得出最大值。
方法二:单调栈法。求连续柱子中所能笼盖的最大面积。基本思想和方法一一致:以每个元素为基准获取左右两侧小于该元素的位置,求得这段距离的面积。具体实现上维持一个单调递减的单调栈,单调递减是结果,当小于当前元素就直接进行计算而不是入栈了。
两种计算情况,当high[i] >= high[stack.peek()],直接入栈,反之进行循环操作。
另外,注意数组左右两侧需要加入数值0,避免单调数字排列没有进行计算的条件。
2.代码实现
// 暴力解法
class Solution {
public int largestRectangleArea(int[] heights) {
int len = heights.length;
if (len == 0) {
return len;
}
int res = 0;
// 以当前元素高度为基准的最大面积
for (int i = 0; i < len; i++) {
// 向左遍历
int left = i;
int curHeight = heights[i];
while (left > 0 && heights[left - 1] >= curHeight) {
left--;
}
// 向右遍历
int right = i;
while (right < len - 1 && heights[right + 1] >= curHeight) {
right++;
}
int s = curHeight * (right - left + 1);
res = Math.max(s, res);
}
return res;
}
}
// 单调栈法
class Solution {
public int largestRectangleArea(int[] heights) {
int result = 0;
int[] high = new int[heights.length + 2];
for (int i = 1; i <= heights.length; i++) {
high[i] = heights[i - 1];
}
Stack<Integer> stack = new Stack<>();
stack.push(0);
for (int i = 1; i < high.length; i++) {
if (high[i] >= high[stack.peek()]) {
stack.push(i);
} else {
while (!stack.isEmpty() && high[i] < high[stack.peek()]) {
int mid = stack.pop();
if (!stack.isEmpty()) {
int left = stack.peek();
int diff = i - left - 1;
int s = diff * high[mid];
result = Math.max(result, s);
}
}
stack.push(i);
}
}
return result;
}
}
3.复杂度分析
时间复杂度:O(N^2).
空间复杂度:O(N).