问题
例子
思路
-
方法1 暴力法 O(n^2)
计算以每一列为高的面积
即分别向该列左和右进行查找,找到连续的列高>=该列高的长度,以此为宽
-
方法2
同方法1图,找到两个边界【边界<面积的高】,把要计算的面积给包起来,第一个和最后一个缺少边界,故在两边添加0
使用一个递增栈【不会降,可相等】,保存每个高的下标,因为面积=高*宽,保存下标也可以得到宽
遍历数组,如果元素<栈顶,
即是栈顶的右边界,栈顶的下面<栈顶,是栈顶的右边界,计算以栈顶为高的面积【当有两个相同的元素在栈中时,计算左边元素时的面积是本来想要的面积】
否则,压栈。
代码
//方法1
class Solution {
public int largestRectangleArea(int[] arr) {
int res = 0;
for(int i=0; i<arr.length; i++) {
int left=i-1;
while(left>=0 && arr[left]>=arr[i])
left--;
left++;
int right=i+1;
while(right<arr.length && arr[right]>=arr[i])
right++;
right--;
res = Math.max(res, (right-left+1)*arr[i]);
}
return res;
}
}
//方法2
class Solution {
public int largestRectangleArea(int[] arr) {
int res = 0;
//添加两个边界
List<Integer> list = new ArrayList<>();
list.add(0);
for(int n : arr) list.add(n);
list.add(0);
//存下标,方便进行
Stack<Integer> s = new Stack<>();
for(int i=0; i<list.size(); i++) {
//找到两个边界
while(s.size()>0 && list.get(i)<list.get(s.peek()))
{
int temp = s.pop();
int left = s.peek()+1;
res = Math.max(res, (i-1-left+1)*list.get(temp));
}
//每个下标都要进栈,因为从栈出来时才以该列为高才进行计算
s.push(i);
}
return res;
}
}