LeetCode Top 100 Liked Questions 84. Largest Rectangle in Histogram (Java版; 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.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]
The largest rectangle is shown in the shaded area, which has area = 10 unit.
Example:
Input: [2,1,5,6,2,3]
Output: 10
class Solution {
public int largestRectangleArea ( int [ ] heights) {
int n = heights. length;
if ( n== 0 ) {
return 0 ;
}
Stack< Integer> s = new Stack < > ( ) ;
s. push ( - 1 ) ;
int max = 0 ;
for ( int i= 0 ; i< n; i++ ) {
while ( s. size ( ) != 1 && heights[ i] < heights[ s. peek ( ) ] ) {
int j = s. pop ( ) ;
max = Math. max ( max, ( i- s. peek ( ) - 1 ) * heights[ j] ) ;
}
s. push ( i) ;
}
while ( s. size ( ) != 1 ) {
int j = s. pop ( ) ;
max = Math. max ( max, ( n- s. peek ( ) - 1 ) * heights[ j] ) ;
}
return max;
}
}
第一次做, 分治算法; 核心: 最大面积矩形是以下三种情况中的某一种, (1)以最矮柱子为高,向两端扩展的矩形, (2)最矮柱子左边的最大矩形, (3)最矮柱子右边的最大矩形; 我用分治法的时候考虑了这么一种情况, 如果数组只有两个元素, 最小值时靠右的那个, 再次递归时, 有左部分, 但是没有右部分了, 所以我提前判断了是否有左右部分, 不过也可以直接使用if(left>right)这个递归终止条件, 不用提前判断是否有左右部分; 844ms
复杂度分析
时间复杂度:平均开销:O(nlogn); 最坏情况:O(n^2)
如果数组中的数字是有序的,分治算法将没有任何优化效果。
空间复杂度:O(n)。最坏情况下递归需要 O(n) 的空间。
class Solution {
public int largestRectangleArea ( int [ ] heights) {
if ( heights== null || heights. length== 0 )
return 0 ;
int res = Core ( heights, 0 , heights. length- 1 ) ;
return res;
}
public int Core ( int [ ] heights, int left, int right) {
if ( left== right)
return heights[ left] ;
int minIndex= left;
for ( int i= left+ 1 ; i<= right; i++ )
minIndex = heights[ i] < heights[ minIndex] ? i : minIndex;
int curr = ( right - left + 1 ) * heights[ minIndex] ;
int leftArea= 0 , rightArea = 0 ;
if ( minIndex- 1 >= left)
leftArea = Core ( heights, left, minIndex- 1 ) ;
if ( minIndex+ 1 <= right)
rightArea = Core ( heights, minIndex+ 1 , right) ;
return Math. max ( Math. max ( curr, leftArea) , rightArea) ;
}
}
第一次做, 单调栈:栈底到栈顶递增; 遍历阶段, 清算阶段; 栈中存索引; 初始时栈中压入-1, 为的是计算栈中倒数第二个元素对应的矩形面积; 以弹出的元素对应的高度作为矩形的高度进行计算; 注意遍历阶段和清算阶段面积公式的差别; 和LeetCode32(Hard)很像; 29ms
import java. util. Stack;
class Solution {
public int largestRectangleArea ( int [ ] heights) {
if ( heights== null || heights. length== 0 )
return 0 ;
Stack< Integer> s = new Stack < > ( ) ;
s. push ( - 1 ) ;
int res= 0 , curr, index;
for ( int i= 0 ; i< heights. length; i++ ) {
if ( s. size ( ) == 1 )
s. push ( i) ;
else {
if ( heights[ i] >= heights[ s. peek ( ) ] ) {
s. push ( i) ;
}
else {
while ( s. size ( ) != 1 && heights[ s. peek ( ) ] > heights[ i] ) {
index = s. pop ( ) ;
curr = ( i - s. peek ( ) - 1 ) * heights[ index] ;
res = Math. max ( res, curr) ;
}
s. push ( i) ;
}
}
}
while ( s. size ( ) != 1 ) {
index = s. pop ( ) ;
curr = ( heights. length - 1 - s. peek ( ) ) * heights[ index] ;
res = Math. max ( res, curr) ;
}
return res;
}
}
题解, 单调栈解法, 写的比我简洁很多
public class Solution {
public int largestRectangleArea ( int [ ] heights) {
Stack < Integer > stack = new Stack < > ( ) ;
stack. push ( - 1 ) ;
int maxarea = 0 ;
for ( int i = 0 ; i < heights. length; ++ i) {
while ( stack. peek ( ) != - 1 && heights[ stack. peek ( ) ] >= heights[ i] )
maxarea = Math. max ( maxarea, heights[ stack. pop ( ) ] * ( i - stack. peek ( ) - 1 ) ) ;
stack. push ( i) ;
}
while ( stack. peek ( ) != - 1 )
maxarea = Math. max ( maxarea, heights[ stack. pop ( ) ] * ( heights. length - stack. peek ( ) - 1 ) ) ;
return maxarea;
}
}
题解, 分支算法, 主要注意递归终止条件; 我用分治法的时候考虑了这么一种情况, 如果数组只有两个元素, 最小值时靠右的那个, 再次递归时, 有左部分, 但是没有右部分了, 所以我提前判断了是否有左右部分, 不过也可以直接使用if(left>right)这个递归终止条件, 不用提前判断是否有左右部分
public class Solution {
public int calculateArea ( int [ ] heights, int start, int end) {
if ( start > end)
return 0 ;
int minindex = start;
for ( int i = start; i <= end; i++ )
if ( heights[ minindex] > heights[ i] )
minindex = i;
return Math. max ( heights[ minindex] * ( end - start + 1 ) , Math. max ( calculateArea ( heights, start, minindex - 1 ) , calculateArea ( heights, minindex + 1 , end) ) ) ;
}
public int largestRectangleArea ( int [ ] heights) {
return calculateArea ( heights, 0 , heights. length - 1 ) ;
}
}