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.
For example,
Given heights = [2,1,5,6,2,3]
,
return 10.
O(n^2)的答案… LTE,优化后的方案是经典的栈的思路,注意几个点:
class Solution {
public int largestRectangleArea(int[] heights) {
int ret = 0;
//维护一个递增序列的栈,在不满足条件的时候弹出
Stack stack = new Stack<>();
if(heights.length == 0)return ret;
//边界条件
stack.push(0);
for(int i= 1; i
一个更加精简的版本…虽然没有什么区别
public int largestRectangleArea(int[] h) {
int n = h.length, i = 0, max = 0;
Stack s = new Stack<>();
while (i < n) {
// as long as the current bar is shorter than the last one in the stack
// we keep popping out the stack and calculate the area based on
// the popped bar
while (!s.isEmpty() && h[i] < h[s.peek()]) {
// tricky part is how to handle the index of the left bound
max = Math.max(max, h[s.pop()] * (i - (s.isEmpty() ? 0 : s.peek() + 1)));
}
// put current bar's index to the stack
s.push(i++);
}
// finally pop out any bar left in the stack and calculate the area based on it
while (!s.isEmpty()) {
max = Math.max(max, h[s.pop()] * (n - (s.isEmpty() ? 0 : s.peek() + 1)));
}
return max;
}
这个思路…虽然在leetcode上测试效果更好,但是其实你分析一下就知道…O(n^2)
public class Solution {
public static int largestRectangleArea(int[] height) {
if (height == null || height.length == 0) {
return 0;
}
int[] lessFromLeft = new int[height.length]; // idx of the first bar the left that is lower than current
int[] lessFromRight = new int[height.length]; // idx of the first bar the right that is lower than current
lessFromRight[height.length - 1] = height.length;
lessFromLeft[0] = -1;
for (int i = 1; i < height.length; i++) {
int p = i - 1;
while (p >= 0 && height[p] >= height[i]) {
p = lessFromLeft[p];
}
lessFromLeft[i] = p;
}
for (int i = height.length - 2; i >= 0; i--) {
int p = i + 1;
while (p < height.length && height[p] >= height[i]) {
p = lessFromRight[p];
}
lessFromRight[i] = p;
}
int maxArea = 0;
for (int i = 0; i < height.length; i++) {
maxArea = Math.max(maxArea, height[i] * (lessFromRight[i] - lessFromLeft[i] - 1));
}
return maxArea;
}
}
递归的思路…分析一下时间复杂度…其实是O(n^2)
Find the minimum height column with index min. The max area should exist among three possible answers:
sub-problem in index [0 ~ min]
sub-problem in index [min + 1 ~ len - 1]
height[min] * (len - 0)
public class Solution {
public int largestRectangleArea(int[] heights) {
if (heights == null || heights.length == 0) return 0;
return getMax(heights, 0, heights.length);
}
int getMax(int[] heights, int s, int e) {
if (s + 1 >= e) return heights[s];
int min = s;
boolean sorted = true;
for (int i = s; i < e; i++) {
if (i > s && heights[i] < heights[i - 1]) sorted = false;
if (heights[min] > heights[i]) min = i;
}
if (sorted) {
int max = 0;
for (int i = s; i < e; i++) {
max = Math.max(max, heights[i] * (e - i));
}
return max;
}
int left = (min > s) ? getMax(heights, s, min) : 0;
int right = (min < e - 1) ? getMax(heights, min + 1, e) : 0;
return Math.max(Math.max(left, right), (e - s) * heights[min]);
}
}