1.题目描述:
给定n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为1。求在该柱状图中,能够勾勒出来的矩形的最大面积。
2.双指针:
做法与leetcode42. 接雨水类似,但是是找到当前柱左右比它小的第一个柱,求差值计算面积,超时了。
class Solution {
public int largestRectangleArea(int[] heights) {
int res = 0;
for (int i = 0; i < heights.length; i++) {
int left = -1;//首尾扩容一下
int right = heights.length;//
for (int j = i - 1; j >= 0; j--) {
if (heights[j] < heights[i]) {
left = j;
break;
}
}
for (int k = i + 1; k < heights.length; k++) {
if (heights[k] < heights[i]) {
right = k;
break;
}
}
res = Math.max(res, (right - left - 1) * heights[i]);
}
return res;
}
}
3.动态规划:
这里动态规划在推导当前柱左右比它小的第一个柱时,不像leetcode42. 接雨水这么简单,需要通过while循环得到。
class Solution {
public int largestRectangleArea(int[] heights) {
int[] leftMin = new int[heights.length];
int[] rightMin = new int[heights.length];
leftMin[0] = -1;
rightMin[heights.length - 1] = heights.length;
int res = 0;
for (int i = 1; i < heights.length; i++) {
int temp = i - 1;
while (temp >= 0 && heights[temp] >= heights[i]) temp = leftMin[temp];
leftMin[i] = temp;
}
for (int i = heights.length - 2; i >= 0; i--) {
int temp = i + 1;
while (temp < heights.length && heights[temp] >= heights[i]) temp = rightMin[temp];
rightMin[i] = temp;
}
for (int i = 0; i < heights.length; i++) {
res = Math.max(res, (rightMin[i] - leftMin[i] - 1) * heights[i]);
}
return res;
}
}
4.单调栈:
需要找到当前柱左右最小最近的柱,单调栈使用栈头到栈底从大到小排列即可,同时为了方便处理首位元素的边界条件,对原来的数组进行扩容。
class Solution {
public int largestRectangleArea(int[] heights) {
int[] newHeights = new int[heights.length + 2];
for (int i = 1; i < heights.length + 1; i++) {
newHeights[i] = heights[i - 1];
}
Stack<Integer> stack = new Stack<>();
int res = 0;
for (int i = 0; i < newHeights.length; i++) {
while (!stack.isEmpty() && newHeights[i] < newHeights[stack.peek()]) {
int temp = stack.pop();
if (!stack.isEmpty()) {
int w = i - stack.peek() - 1;
int h = newHeights[temp];
res = Math.max(res, w * h);
}
}
stack.push(i);
}
return res;
}
}