Article Directory
topic:
Given n non-negative integers, they are used to represent the height of each column in the histogram. Each pillar is adjacent to each other and has a width of 1.
Find the maximum area of the rectangle that can be outlined in the histogram.
The above is an example of a histogram, where the width of each column is 1, and the given height is [2,1,5,6,2,3].
The shaded part in the figure is the largest rectangular area that can be outlined, and its area is 10 units.
Example:
输入: [2,1,5,6,2,3]
输出: 10
Solution 1: Violence
/**
* 思路:
* 暴力,双层for
* 记录最大面积max,和最小柱子的高度
* 不断向前遍历,找到每个棒子所在范围内的最小值,更新min和area
*
* 注意:1根柱子也可以计算面积
*/
public int largestRectangleArea(int[] heights) {
int max=0,minHeight;
for (int i=0;i<heights.length;i++){
minHeight=heights[i];
for (int j=i;j<heights.length;j++){
minHeight=minHeight>heights[j]?heights[j]:minHeight;
int area = minHeight * (j - i + 1);
max=max>area?max:area;
}
}
return max;
}
Time complexity: On^2
Space complexity: O1
Solution 2: Stack implementation
/**
* 思路:
* 核心思路:
* 确定每个柱子的左右边界,一旦确定就进行area计算(确定每个棒子最大可能的面积,知道了所有的柱子最大可能面积就能找到柱状图最大面积)
* 不断的向前遍历数组,我们是一定可以知道的是每个棒子的左边界(左边的棒子已经遍历到),但是棒子的右边界无法确定(右边的棒子还未遍历到)。
*
* 栈能很好能实现这个思路
* 栈中存放初始值-1(方便第一个棒子计算面积),栈中存放的是数组的下标
* 遍历数组
* 如果当前值比栈中元素大就入栈(这样当前柱子的左边界就是他们在栈中的下一个元素)
* 如果当前值比栈中元素小就把栈中元素都出栈!!出栈元素的左右边界相当于确定了(左边界是栈中的下一个元素,右边界就是这个比他小的元素),计算area和max进行比较。之后入栈当前值
* 遍历完后,清空栈,计算面积:这个时候剩余元素的右边界都是heights.length,左边界依旧是栈中下一个元素
*/
public int largestRectangleArea(int[] heights) {
ArrayDeque<Integer> stack = new ArrayDeque<>();
stack.push(-1);
int max=0;
for (int i=0;i<heights.length;i++){
while (stack.peek()!=-1&&heights[i]<heights[stack.peek()]){
int bar_heigh=heights[stack.pop()];
int area=bar_heigh*(i-stack.peek()-1);
max=area>max?area:max;
}
stack.push(i);
}
while (stack.peek()!=-1){
int bar_heigh = heights[stack.pop()];
int area=bar_heigh*(heights.length-stack.peek()-1);
max=area>max?area:max;
}
return max;
}
Time complexity: On
Space complexity: On
Solution 3: Divide and conquer
/**
* 思路:
* 核心思路:在最小值的左侧,和右侧才可能出现更大的面积
*
* 分治
* 终止条件,start>end
* 找到数组的最小值,求面积
* 子问题:在左右侧在找最大面积
*/
public int largestRectangleArea(int[] heights) {
return divideConquer(0,heights.length-1,heights);
}
private int divideConquer(int start, int end, int[] heights) {
//Terminator
if (start>end){
return 0;
}
//process current logic
int min=start;
for (int i=start;i<=end;i++){
if (heights[i]<heights[min]){
min=i;
}
}
int area=heights[min]*(end-start+1);
//drill down
return Math.max(area,Math.max(divideConquer(start,min-1,heights),divideConquer(min+1,end,heights)));
//restore store
}
Time complexity: On^2
Space complexity: O1