84. 柱状图中最大的矩形
难度:困难 2020/5/30每日一题打卡√
单调栈题目:
题目描述
解题思路
参考题解:【柱状图中最大的矩形】单调栈入门,使用单调栈快速寻找边界
暴力解法、栈(单调栈、哨兵技巧)
这道题和接雨水的那道题好像啊,那道题求凹下去的面积,这道题求凸起的面积。还是用单调栈来写,栈里面存放的元素保持递增关系,作用是快速确定边界。如果新元素比栈顶元素严格小,那么就确定了右边界,再加上栈里使递增关系,所以左边界也能确定。把当前栈顶元素出栈,计算面积,比较最大值。
代码模板:
stack<int> st;
for(int i = 0; i < nums.size(); i++)
{
while(!st.empty() && st.top() > nums[i])
{
st.pop();
}
st.push(nums[i]);
}
我自己写的,判断栈非空有点麻烦,还要单独处理遍历完栈中剩余的元素
public int largestRectangleArea(int[] heights) {
int max = 0,left = 0,top = 0;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < heights.length; i++) {
if(stack.isEmpty()) {
stack.push(i);
}else {
top = heights[stack.peek()];
if(heights[i] >= top) { //使栈内保持递增关系
stack.push(i); //把下标入栈
}else { //如果栈顶元素小于当前元素,出栈直到满足递增关系
while(!stack.isEmpty() && heights[stack.peek()] > heights[i] ) {
top = heights[stack.pop()];
//栈中相邻的元素下标不一定相邻,要看前一位
left = stack.isEmpty()?-1:stack.peek();
//每出栈一个元素,计算这个位置高度能组成的面积
max = Math.max(max, top*(i-left-1));
}
stack.push(i);
}
}
}
//处理栈里面元素非空的情况
while(!stack.isEmpty()) {
top = heights[stack.pop()];
left = stack.isEmpty()?-1:stack.peek();
//每出栈一个元素,计算这个位置高度能组成的面积
max = Math.max(max, top*(heights.length-left-1));
}
return max;
}
解决办法是往数组最前面和最后面添加两个哨兵元素,他们不会影响结果,但是会简化边界的处理。
//增加两个哨兵
public int largestRectangleArea(int[] heights) {
int max = 0,len = heights.length,top = 0,left = 0;
int[] newHeights = new int[len + 2];
System.arraycopy(heights, 0, newHeights, 1, len);
len += 2;
heights = newHeights;
Stack<Integer> stack = new Stack<>();
stack.add(0);
for (int i = 1; i < len; i++) {
while(heights[stack.peek()] > heights[i]) {
top = heights[stack.pop()];
left = stack.peek();
max = Math.max(max, top*(i-left-1));
}
stack.push(i);
}
return max;
}