-
题目描述(力扣题库 84):
-
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
-
-
解题思想:
-
单调栈:
- 利用先进后出的思想, 先算出长度更高的柱子所能勾勒出的矩形的面积.
-
-
我们从左到右遍历给定的直方图数组, 与此同时, 使用一个单调递增的栈来存储直方图柱子的索引。这样,栈顶元素对应的柱子高度始终是递增的。
-
当我们遇到一个柱子高度小于栈顶柱子高度时,说明找到了一个可以计算矩形面积的位置。这是因为在单调递增栈中,栈顶元素右侧第一个小于自身高度的柱子就是该柱子右边界。因此,我们弹出栈顶元素,计算以该柱子高度为矩形高度的最大矩形面积。矩形的宽度可以通过当前位置索引与栈顶元素索引之差来确定。
-
重复之前步骤直到栈为空或者当前柱子高度大于栈顶柱子高度。这个步骤保证了栈内的柱子高度始终是单调递增的,且找到了所有可以计算矩形面积的位置。
-
-
其中最为关键的是, 得到柱子所能渲染的矩形的宽度
-
解题步骤:
-
1.初始化变量和数据结构:
- 初始化一个整数变量
area
用于保存最大面积。 - 初始化一个双端队列
stack
用于保存直方图中柱子的索引。
- 初始化一个整数变量
-
2.遍历直方图:
- 使用 for 循环遍历直方图中的每个柱子。
-
3.维护单调递增栈:
- 在循环中,每次都会检查当前柱子的高度是否小于栈顶柱子的高度,如果是,则说明栈顶柱子的右边界可以确定,可以计算以栈顶柱子为高度的最大矩形面积。在这个过程中,不断地从栈中弹出柱子,直到当前柱子的高度不小于栈顶柱子的高度,或者栈为空。
- 弹出柱子时,计算以弹出柱子的高度为高度的矩形面积。计算面积的方法是通过弹出柱子的索引和当前柱子的索引来计算宽度,即
width = i - stack.peekLast() - 1
。 - 每次计算完矩形面积后,更新
area
的值为当前面积和历史最大面积中的较大值。
-
4.处理剩余的柱子:
- 遍历完成后,如果栈中还有柱子,说明这些柱子的右边界是整个直方图的末尾,因此可以以这些柱子为高度计算最大矩形面积。这部分的处理与上面的过程类似。
-
5.返回最大面积:
- 返回最大面积
area
。
- 返回最大面积
-
这个算法的关键思想是使用单调递增栈来找到每个柱子的左右边界,从而计算以每个柱子为高度的最大矩形面积,然后从中选出最大值。
-
-
以下是代码实现:
-
class Solution { public int largestRectangleArea(int[] heights){ if(heights.length == 0) return 0; if(heights.length == 1) return heights[0]; int area = 0; Deque<Integer> stack = new ArrayDeque<>(); for (int i = 0; i < heights.length; i++) { while(!stack.isEmpty() && heights[stack.peekLast()] > heights[i]){ int height = heights[stack.removeLast()]; int width; if(stack.isEmpty()) width = i; else width = i - stack.peekLast() - 1; area = Math.max(area, height * width); } stack.addLast(i); } while(!stack.isEmpty()){ int height = heights[stack.removeLast()]; int width; if(stack.isEmpty()) width = heights.length; else width = heights.length - stack.peekLast() - 1; area = Math.max(area, height * width); } return area; } }
-
-