84. Largest Rectangle in Histogram
1 | public class Solution { |
Brute force.把所有bar构成的pair走一遍,求bar构成的pair表示左右两个边界.从(0,0)开始,然后是(0,1),(0,2)…(0,heights.length-1),走的过程中始终维护着一个变量来记录目前遇到的最小height是多少.这样就不用确定pair后在遍历pair确定的范围内的最小值了.
时间复杂度:O(n^2)空间复杂度:O(1)
1 | class Solution { |
这道题的关键就是让每个bar都试一下成为minimum,也就是如果某个bar比方说height[i]这个bar, 它是某个rectangle的minimum的话,那么这样的rectangle最大能够多大?此时我们需要知道height[i]的previous smaller以及next smaller, 因为超过这两个边界, 构成的rectangle中heights[i]就不是minimum了. 那这不正是monostack干的事情: 在一个位置, monostack能告诉我们该位置数字的previous smaller, 同时被pop的出来的数字知道自己的next smaller是谁.如果一个数字被pop出来,那么它就满足做minimum的条件了, 我们就可以求该数对应的height做minimu的时候, 最大的rectangle是多少了. 因为此时的heights[i]是它的next smaller, 而栈里如果有数字的话, 那这个数字就是它的previous smaller的index, 如果栈为空, 就说明没有比它小的数字, 那么可以认为左侧都比它大. 此时构成的rectangle的高就是heights[stack.pop()], stack.pop()表示那个要被pop出来的数字, rectangle的长就是i - (previous smaller idx or -1) - 1. 这是因为i和previous smaller idx都不算在这个rectangle里面因为它们都比heights[stack.pop()]小, 我们要的是让heights[stack.pop()]作为rectangle的minimum. 由于我们计算时左右的边界都是exclusive的, 因此是right - left - 1. 为了保证这个逻辑统一, 当stack是空的时候, 我们人为让left == -1, 也就是index 0左侧一个位置, 这样right和left框起来的区域就是长, 并且不包含left和right.
总结一句话就是让每个bar都作为minimum, 看这样它们能组成的rectangle的area最大是多少. 之所以这样能得到答案是是因为最终的答案对应的那种截取情况, 一定有一个bar或某几个bar最小, 那么如果我们知道每个bar当它作为minimum时能得到的最大rectangle area的时候, 我们就能得到全局最大的area.
时间复杂度: O(n)
空间复杂度: O(n)