LeetCode 84. 柱状图中最大的矩形
Posted 菜鸡的世界
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 84. 柱状图中最大的矩形相关的知识,希望对你有一定的参考价值。
https://leetcode-cn.com/problems/largest-rectangle-in-histogram/
这个题没有做啥要求,暴力也能过。
其实这个题有点像接雨水一样,看题解有人用扫描法也做出来了。但是还是用单调栈的方法吧,(明明22天前做出来了,今天却做不出来???)
public int largestRectangleArea(int[] heights) { LinkedList<Integer> stack = new LinkedList<>(); int max = 0; for(int i = 0; i < heights.length; i++){ while(!stack.isEmpty() && heights[stack.getLast()] > heights[i]){ int j = stack.removeLast(); max = Math.max(max, heights[j] * (stack.isEmpty()?i:(i-stack.getLast() - 1))); } stack.addLast(i); } while(!stack.isEmpty()){ int j = stack.removeLast(); max = Math.max(max, heights[j] * (stack.isEmpty()?heights.length:(heights.length-stack.getLast() - 1))); } return max; }
其实还是很容易理解的,我们维护一个递增栈,如果遇到一个比栈顶元素要小的值,就开始计算最大面积。
我们把数组下标抽象成一排木板并排,然后数组下标就是木板左下角的坐标。
遇到一个小的元素,我们就依次计算栈顶元素能维护到的最大面积。
上图我们第一个遇到递减的情况是数组下标为1的时候,那么我们栈中只有一个元素0,我们把它出栈。
新面积计算的方法:栈顶元素的木板长度 * (如果栈为空,那么就是当前数组下标,否则就是 当前数组下标- 栈顶元素下标 - 1);
然后我们去比较max和新面积的大小。
我们重复这个步骤,直到栈为空,或者栈顶元素比当前下标元素还要小的情况
当然这种方法有可能会出现2,1,5,6,7,8后面全部都是递增的情况,我们就需要在数组的最后边再添加一个长度为0的木板,由于java传的是数组我不想去复制一次,所以就再扫一次栈好了。
总的来说,我对做过的题有印象,但是有些题目记忆不是很深刻,这题单调栈和全递增的情况后面我都想出来了,就是没有处理好面积计算的时候栈为空的情况。看来还是得多回忆一下老题。
看到一个单调栈的总结,复制过来记忆一下。LeetCode上单调栈的问题也很多,像接雨水,最大矩形面积,最大正方形面积这种,这个也是比较考验思维的一种题,希望自己可以多回忆一下。
// 明确单调栈能够解决的问题
// 1.找右侧第一个更小 增栈
// 2.找右侧第一个更大 减栈
// 3.找左侧第一个更小 增栈
// 4.找左侧第一个更大 减栈
2020年9月14日更新
其实这个题和之前接雨水的两个题一样,都是可以用双指针去完成的。
我们只需要维护left和right数组即可。
这里的数组指的是 left[i]:第i个柱子左手第一个比当前柱子小的下标。
right[i]: 第i个柱子右手第一个比当前柱子小的下标。
我们计算max的方法就是 (right[i] - left[i] - 1) * height[i]。
class Solution { public int largestRectangleArea(int[] heights) { /* 使用 left 和 right 数组 记录 从 i 左右两边延伸,第一个比 i 位置小的柱子索引位置 那么第 i 根柱子能组成面积的宽度就是 right[i] - left[i] - 1 */ int n = heights.length; if(n == 0){ return 0; } int[] left = new int[n]; int[] right = new int[n]; //第一根柱子,左边不存在比它小的 left[0] = - 1; //最后一根柱子,右边不存在比它小的 right[n - 1] = n; for(int i = 1; i < n; i++){ int temp = i - 1; while(temp >= 0 && heights[temp] >= heights[i]){ temp = left[temp]; } //当上述循环 break 后, temp 即为左边第一根小于 i 位置的柱子 left[i] = temp; } for(int i = n - 2; i >= 0; i--){ int temp = i + 1; while(temp < n && heights[temp] >= heights[i]){ temp = right[temp]; } //当上述循环 break 后, temp 即为右边第一根小于 i 位置的柱子 right[i] = temp; } int maxArea = 0; for(int i = 0; i < n; i++){ int width = right[i] - left[i] - 1; maxArea = Math.max(maxArea, heights[i] * width); } return maxArea; } }
以上是关于LeetCode 84. 柱状图中最大的矩形的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 84. 柱状图中最大的矩形 | Python