84-柱状图中的最大矩形

84-柱状图中的最大矩形

前言:实习的公司真是个学习的好地方,展南安排任务慢慢开始对接测试人员,学宇教我上班划划水!有问题就去烦萌萌!嘿嘿,今天看到萌萌在刷力扣,给我发来了这道题

力扣原题https://leetcode-cn.com/problems/largest-rectangle-in-histogram/

题目我就不贴了,关键是第一次接触到单调栈。


1. 暴力法

思路很简单,遍历,向左向右找到比当前heights[i]低的柱,下标为left和right,然后底(right - left - 1) * 高(heights[i])

1
2
3
4
5
6
7
8
9
10
11
12
public int largestRectangleArea(int[] heights) {
if (heights == null || heights.length == 0) return 0;
int max = Integer.MIN_VALUE;
for (int i = 0; i < heights.length; i++) {
//往左找,往右找
int left = i, right = i;
while (left >= 0 && heights[left] >= heights[i]) left--;
while (right < heights.length && heights[right] >= heights[i]) right++;
max = Math.max(max, heights[i] * (right - left - 1));
}
return max;
}

用时1034ms!只有java能过,python使用这种方法超时。

2. 单调栈

第一次接触这个概念,但是其实并不是第一次接触单调栈的题目。这个不是一个数据结构,只是一种思维,让栈的元素单调递增或者递减,使用的场景有:遍历到i时,需要往后/前看,看到满足某个条件时需要跟i作比较。

通过一些具体题目来看什么时候使用:

  • 本题:在柱状图中,能够勾勒出来的矩形的最大面积。遍历到i时,往后找heights[right]比heights[i]小的元素,说明i处最大的矩形高为heights[i],宽为right - i - 1
  • 能看的到的楼:趋势科技秋招笔试题,大概是有一排高低不同的楼,人依次站在每栋楼的楼顶往后看,能看到多少栋楼的楼顶(趋势科技改了题目,可以往前看也可以往后看,当时不知道单调栈的概念)

大佬讲解https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/bao-li-jie-fa-zhan-by-liweiwei1419/

我直接贴完整代码

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
/**
* 单调栈,思路:
* 栈中存的是下标,代表了矩形宽度的起点start,i代表end位置,heights[i]代表了当前柱状图的高度,heights[stack.peek]就代表栈顶高度
* 低高(12)类型,入栈:因此栈顶的值就是:以栈顶柱状图高度(heights[stack.peek])为矩形的起点start
* 高低(21)类型,出栈:遇到比栈顶对应的高度小的(heights[i] < heights[stack.peek]),说明以heights[stack.peek]为高的矩形被确定,宽度为i - stack.peek() - 1
* 循环上述出栈过程直到满足12类型,每次出栈对比累计最大值和当前矩形最大值
* 哨兵的添加:最后栈中剩下的满足12类型,为了方便继续比较,则增加末尾哨兵为0变成120,于是遍历到0的时候20满足了21类型,2出栈,10也满足21类型,结束。
*/
public class eight_four_柱状图中的最大矩形_other {

@Test
public void test(){
int[] heights = {2, 1, 5, 6, 2, 3};
int res = largestRectangleArea(heights);
System.out.println(res);
}

public int largestRectangleArea(int[] heights) {
int len = heights.length;
if (len == 0) return 0;
if (len == 1) return heights[0];

int res = 0;
int[] newHeights = new int[len + 2];
newHeights[0] = 0;
System.arraycopy(heights, 0, newHeights, 1, len);
newHeights[len + 1] = 0;
len += 2;
heights = newHeights;

Deque<Integer> stack = new ArrayDeque<>(len);
// 先放入哨兵,在循环里就不用做非空判断
stack.addLast(0);

for (int i = 1; i < len; i++) {
while (heights[i] < heights[stack.peekLast()]) {
int curHeight = heights[stack.pollLast()];
int curWidth = i - stack.peekLast() - 1;
res = Math.max(res, curHeight * curWidth);
}
stack.addLast(i);
}
return res;
}
}

10ms,估计时间的消耗在System.arraycopy,还有别的写法,占坑。

3. 其他单调栈系列题目

其他单调栈系列题可以点这里

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×