Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
The largest rectangle is shown in the shaded area, which has area = 10 unit.
Example:
1 2
Input: [2,1,5,6,2,3] Output: 10
Solution
Language: Java
暴力法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution{ publicintlargestRectangleArea(int[] heights){ if (heights == null || heights.length == 0) { return0; } int largestArea = 0; for (int i = 0; i < heights.length; i++) { int minHeight = Integer.MAX_VALUE; for (int j = i; j < heights.length; j++) { minHeight = Math.min(heights[j], minHeight); largestArea = Math.max(largestArea, minHeight * (j - i + 1)); } } return largestArea; } }
分治法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution{ publicintcalculateArea(int[] heights, int start, int end){ if (start > end) { return0; } int minIndex = start; for (int i = start; i <= end; i++) { if (heights[i] < heights[minIndex]) { minIndex = i; } } return Math.max(heights[minIndex] * (end - start + 1), Math.max(calculateArea(heights, start, minIndex - 1), calculateArea(heights, minIndex + 1, end))); } publicintlargestRectangleArea(int[] heights){ return calculateArea(heights, 0, heights.length - 1); } }
单调栈
维护一个单调递增栈,逐个将元素 push 到栈里。push 进去之前先把 >= 自己的元素 pop 出来。 每次从栈中 pop 出一个数的时候,就找到了往左数比它小的第一个数(当前栈顶)和往右数比它小的第一个数(即将入栈的数), 从而可以计算出这两个数中间的部分宽度 * 被pop出的数,就是以这个被pop出来的数为最低的那个直方向两边展开的最大矩阵面积。 因为要计算两个数中间的宽度,因此放在 stack 里的是每个数的下标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution{ publicintlargestRectangleArea(int[] heights){ if (heights == null || heights.length == 0) { return0; } Deque<Integer> stack = new ArrayDeque<>(); int max = 0; for (int i = 0; i <= heights.length; i++) { int cur = i == heights.length ? -1 : heights[i]; while (!stack.isEmpty() && heights[stack.peek()] > cur) { int h = heights[stack.pop()]; int w = stack.isEmpty() ? i : i - stack.peek() - 1; max = Math.max(max, h * w); } stack.push(i); } return max; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14
## [84\. Largest Rectangle in Histogram](https://leetcode.com/problems/largest-rectangle-in-histogram/description/)
Difficulty:: **Hard**
Given _n_ non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. ![](https://assets.leetcode.com/uploads/2018/10/12/histogram.png) <small style="display: inline;">Above is a histogram where width of each bar is 1, given height = `[2,1,5,6,2,3]`.</small> ![](https://assets.leetcode.com/uploads/2018/10/12/histogram_area.png) <small style="display: inline;">The largest rectangle is shown in the shaded area, which has area = `10` unit.</small> **Example:**
#### 暴力法 ```java class Solution { public int largestRectangleArea(int[] heights) { if (heights == null || heights.length == 0) { return 0; } int largestArea = 0; for (int i = 0; i < heights.length; i++) { int minHeight = Integer.MAX_VALUE; for (int j = i; j < heights.length; j++) { minHeight = Math.min(heights[j], minHeight); largestArea = Math.max(largestArea, minHeight * (j - i + 1)); } } return largestArea; } }
分治法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution{ publicintcalculateArea(int[] heights, int start, int end){ if (start > end) { return0; } int minIndex = start; for (int i = start; i <= end; i++) { if (heights[i] < heights[minIndex]) { minIndex = i; } } return Math.max(heights[minIndex] * (end - start + 1), Math.max(calculateArea(heights, start, minIndex - 1), calculateArea(heights, minIndex + 1, end))); } publicintlargestRectangleArea(int[] heights){ return calculateArea(heights, 0, heights.length - 1); } }
单调栈
维护一个单调递增栈,逐个将元素 push 到栈里。push 进去之前先把 >= 自己的元素 pop 出来。 每次从栈中 pop 出一个数的时候,就找到了往左数比它小的第一个数(当前栈顶)和往右数比它小的第一个数(即将入栈的数), 从而可以计算出这两个数中间的部分宽度 * 被pop出的数,就是以这个被pop出来的数为最低的那个直方向两边展开的最大矩阵面积。 因为要计算两个数中间的宽度,因此放在 stack 里的是每个数的下标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution{ publicintlargestRectangleArea(int[] heights){ if (heights == null || heights.length == 0) { return0; } Deque<Integer> stack = new ArrayDeque<>(); int max = 0; for (int i = 0; i <= heights.length; i++) { int cur = i == heights.length ? -1 : heights[i]; while (!stack.isEmpty() && heights[stack.peek()] > cur) { int h = heights[stack.pop()]; int w = stack.isEmpty() ? i : i - stack.peek() - 1; max = Math.max(max, h * w); } stack.push(i); } return max; } }