forked from DengWangBao/Leetcode-Java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LargestRectangleInHistogram.java
71 lines (63 loc) · 2.58 KB
/
LargestRectangleInHistogram.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import java.util.Stack;
/**
* 参考https://leetcode.com/articles/largest-rectangle-histogram/
*/
public class LargestRectangleInHistogram {
/**
* 这题关键是对于每根柱子,往两边延伸到某根柱子比自己矮或到边界为止。
* 暴力办法是依次循环,时间复杂度O(n^2),空间复杂度O(n)
* 采用动态规划延伸的时候可以根据之前的结果跳着走,最优时间复杂度O(n),最差时间复杂度O(n^2),平均时间复杂度O(n),空间复杂度O(n)
* 采用压栈的方法最巧妙,时间复杂度O(n),空间复杂度O(n)
*/
// 这种超时了,复杂度O(n^2)
public int largestRectangleArea(int[] heights) {
int max = 0;
for (int i = 0, j, k; i < heights.length; i++) {
for (j = i - 1; j >= 0 && heights[j] >= heights[i]; j--);
for (k = i + 1; k < heights.length && heights[k] >= heights[i]; k++);
max = Math.max(max, (k - j - 1) * heights[i]);
}
return max;
}
/** 注意栈中的是index,不是高度
* 栈保持递增,当出现小于栈顶的元素时,意味着可以计算栈顶可以延伸的矩形面积了
* 其左边界是次栈顶,右边界是当前元素
*/
public int largestRectangleArea2(int[] heights) {
int max = 0;
Stack<Integer> stack = new Stack<Integer>();
for (int i = 0; i <= heights.length; ) {
int height = i == heights.length ? 0 : heights[i];
if (stack.isEmpty() || height > heights[stack.peek()]) {
stack.push(i++);
} else {
int top = stack.pop();
int left = stack.isEmpty() ? 0 : stack.peek() + 1;
/**
* top两边都是比top高的
* [left,i-1]
*/
max = Math.max(max, heights[top] * (i - 1 - left + 1));
}
}
return max;
}
// 耗时4ms
public int largestRectangleArea3(int[] heights) {
int len = heights.length, j;
int[] left = new int[len], right = new int[len];
for (int i = 0; i < len; i++) {
for (j = i; j >= 1 && heights[j - 1] >= heights[i]; j = left[j - 1]);
left[i] = j;
}
for (int i = len - 1; i >= 0; i--) {
for (j = i; j < len - 1 && heights[j + 1] >= heights[i]; j = right[j + 1]);
right[i] = j;
}
int max = 0;
for (int i = 0; i < len; i++) {
max = Math.max(max, (right[i] - left[i] + 1) * heights[i]);
}
return max;
}
}