一、栈
承接Leetcode 84,柱状图算最大矩形面积,把该题入参改为柱状图高度即可
PS:这版本手搓int[]做栈和直接用ArrayDeque做栈,结果仅差2ms;但题84相差近15ms。
public int maximalRectangle(char[][] matrix) {
if (matrix.length == 0) {
return 0;
}
int a = matrix[0].length; // row
int b = matrix.length;
int[] heights = new int[a + 2];
heights[0] = -1;
heights[b + 1] = -1;
int max = 0;
for (int j = 0; j < b; j++) {
// 构建柱状图heights
for (int i = 0; i < a; i++) {
boolean isZero = matrix[j][i] == '0';
heights[i + 1] = isZero ? 0 : heights[i + 1] + 1;
}
max = Math.max(max, largestRectangleArea(heights));
}
return max;
}
// 参考leetcode84题解
public int largestRectangleArea(int[] heights) {
int max = 0;
Deque<Integer> stack = new ArrayDeque<>();
stack.push(0);
for (int i = 1; i < heights.length; i++) {
int curH = heights[i];
while (curH < heights[stack.peek()]) {
int confirmIdx = stack.pop();
max = Math.max(max, heights[confirmIdx] * (i - stack.peek() - 1));
}
stack.push(i);
}
return max;
}
二、dp + 剪枝
自己想的第一版,记录一下。想法就是如何用到dp,那就是左边这个点,和上面这个点 ==> 当前这个点。
dp存的是所有可能最大矩形的左上角点的合集。
分五种情况讨论
左为null,上为null => 自己
左为null,上不为null => 上的最高点
左不为null,上为null => 左的最左点
左不为null,上不为null,左上为null => 上的最高点 + 左的最做点
左不为null,上不为null,左上不为null =>
- 看左边所有的点,取其y值与上的最高点的最小值(因为左边所有点是从最左点遍历的,因此一旦其y值<=最高点的最小值,即可剪枝)
- 若左边所有点的y值都小于最高点,则+上的最高点(否则就已经涵盖,不需要另外再加,算是剪枝的一部分)
class Solution {
public int maximalRectangle(char[][] matrix) {
if (matrix.length <= 0) {
return 0;
}
int aSize = matrix[0].length;
int bSize = matrix.length;
Batch[] first = new Batch[aSize + 1];
Batch[] second = new Batch[aSize + 1];
int maxSize = 0;
for (int j = 1; j < bSize + 1; j++) {
for (int i = 1; i < aSize + 1; i++) {
if (matrix[j - 1][i - 1] == '0') {
second[i]=null;
continue;
}
if (second[i - 1] == null && first[i] == null) {
second[i] = Batch.initSingle(i, j);
} else if (second[i - 1] == null && first[i] != null) {
second[i] = Batch.initUp(first[i], i, j);
} else if (second[i - 1] != null && first[i] == null) {
second[i] = Batch.initLeft(second[i - 1], i, j);
} else {
second[i] = Batch.merge(second[i - 1], first[i], first[i - 1], i, j);
}
maxSize = Math.max(maxSize, second[i].calSize(i, j));
}
for (int i = 1; i < aSize + 1; i++) {
first[i] = second[i];
}
}
return maxSize;
}
static class Batch {
int minX;
int minY;
List<Point> list;
public static Batch init() {
Batch batch = new Batch();
batch.list = new ArrayList<>();
return batch;
}
public static Batch initSingle(int x, int y) {
Batch batch = init();
batch.list.add(Point.init(x, y));
batch.minX = x;
batch.minY = y;
return batch;
}
public static Batch initUp(Batch other, int i, int j) {
return initSingle(i, other.minY);
}
public static Batch initLeft(Batch other, int i, int j) {
return initSingle(other.minX, j);
}
public static Batch merge(Batch left, Batch up, Batch leftUp, int i, int j) {
Batch b = Batch.init();
b.minX = left.minX;
b.minY = up.minY;
if (leftUp == null) {
b.list.add(Point.init(left.minX, j));
b.list.add(Point.init(i, up.minY));
} else {
int minY = up.minY;
for (Point llp : left.list) {
if (minY <= llp.y) {
b.list.add(llp);
} else {
b.list.add(Point.init(llp.x, minY));
break;
}
}
if (up.minY < left.minY)
b.list.add(Point.init(i, minY));
}
return b;
}
public int calSize(int i, int j) {
int max = 0;
for (Point point : list) {
max = Math.max(point.calSize(i, j), max);
}
return max;
}
}
static class Point {
int x;
int y;
public static Point init(int x, int y) {
Point p = new Point();
p.x = x;
p.y = y;
return p;
}
public int calSize(int a, int b) {
return (a - x + 1) * (b - y + 1);
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。