leetcode84 - Largest Rectangle in Histogram - 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.
Example:
Input: [2,1,5,6,2,3]
Output: 10
Stack 递增栈。
想法:遍历的时候,把当前条条和以前的(stack.peek)对比。
当你看到条条比peek高,你知道当前这根条条有希望合并到之后一些条条的答案里(因为后面可能还是递增的),你就先偷懒。只是压入栈,不处理。
当你看到条条比peek矮,比如看到了heights[4] = 2 < 6你不能偷懒了要开始对stack里之前的东西进行一些计算了。计算方法就是在peek比当前条条还高着的情况下,不断pop以前的条条,通过高宽计算面积去打擂台。算完才把这个小矮条压入栈给以后用。
1)高就是当前pop出来的这条的高度,比如5.
2)宽就是被夹在中间的那一段,左边是现在的peek(不被算在内 peek: 如1),右边是遍历过程中的新矮条位置(i: 如4) 这两个左右定位符都不被包括在内,例如此时算出来的宽度是4-1-1。另外解释一下,我们选择这个固定下来anchor住的右边的原因是,我们知道stack里一直递增状态,当我们pop到当前这个位置的时候,我知道之前被pop出来的那些肯定也有当前这条那么高,所以我肯定可以一直延伸到新矮条前面的。
细节:
1.如果遍历完一次后,stack里还剩下东西,还要继续用类似方法处理,这次就是把右边定位在最后一根条条的右边。这个计算可以通过小trick合并到前面的遍历内。
2.如果pop后要算长宽时,发现stack空了,那宽度就是让左边看成index-1了,也就是左边的条条全都包括进来按当前height计算。因为你能把递增栈stack掏空说明你现在pop出来的这条,是你见过有史以来最矮的一条,那么所有前面的都可以贡献了。
这题好难,多跑test多体会多回顾code。
实现1:代码有冗余,但思路直接一些
class Solution { public int largestRectangleArea(int[] heights) { int ans = 0; Stack<Integer> stack = new Stack<>(); for (int i = 0; i < heights.length; i++) { if (stack.isEmpty() || heights[i] >= heights[stack.peek()]) { stack.push(i); } else { while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) { int height = heights[stack.pop()]; int width = stack.isEmpty() ? i : i - 1 - stack.peek(); ans = Math.max(ans, height * width); } stack.push(i); } } // for the case after all the iteration, there's still elements left in the stack. while (!stack.isEmpty()) { int height = heights[stack.pop()]; int width = stack.isEmpty() ? heights.length : heights.length - 1 - stack.peek(); ans = Math.max(ans, height * width); } return ans; } }
实现2:九章,去除冗余,有一些小trick。
public class Solution { public int largestRectangleArea(int[] height) { if (height == null || height.length == 0) { return 0; } Stack<Integer> stack = new Stack<Integer>(); int max = 0; for (int i = 0; i <= height.length; i++) { int curt = (i == height.length) ? -1 : height[i]; while (!stack.isEmpty() && curt <= height[stack.peek()]) { int h = height[stack.pop()]; int w = stack.isEmpty() ? i : i - stack.peek() - 1; max = Math.max(max, h * w); } stack.push(i); } return max; } }