柱狀圖中最大的矩形
給定 n 個非負整數(shù),用來表示柱狀圖中各個柱子的高度扑媚。每個柱子彼此相鄰,且寬度為 1 暑塑。
求在該柱狀圖中,能夠勾勒出來的矩形的最大面積锅必。
以上是柱狀圖的示例事格,其中每個柱子的寬度為 1,給定的高度為 [2,1,5,6,2,3]
。
圖中陰影部分為所能勾勒出的最大矩形面積驹愚,其面積為 10
個單位
示例:
輸入: [2,1,5,6,2,3]
輸出: 10
方法一:暴力
固定高度远搪,向兩邊找邊
public int largestRectangleArea(int[] heights) {
int maxArea = 0;
for (int i = 0; i < heights.length; i++) {
int left = i, right = i;
while (left >= 0 && heights[left] >= heights[i]) {
left--;
}
while (right < heights.length && heights[right] >= heights[i]) {
right++;
}
maxArea = Math.max(maxArea, heights[i] * (right - left - 1));
}
return maxArea;
}
固定邊
public int largestRectangleArea(int[] heights) {
int maxArea = 0;
for (int i = 0; i < heights.length; i++) {
int minHeight = heights[i];
for (int j = i; j < heights.length; j++) {
minHeight = Math.min(minHeight, heights[j]);
maxArea = Math.max(maxArea, minHeight * (j - i + 1));
}
}
return maxArea;
}
方法二:單調(diào)棧
public int largestRectangleArea(int[] heights) {
int maxArea = 0;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < heights.length; i++) {
while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
int height = heights[stack.pop()];
int width;
if (stack.isEmpty()) {
width = i;
} else {
width = i - stack.peek() - 1;
}
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
while (!stack.isEmpty()) {
int height = heights[stack.pop()];
int width;
if (stack.isEmpty()) {
width = heights.length;
} else {
width = heights.length - stack.peek() - 1;
}
maxArea = Math.max(maxArea, height * width);
}
return maxArea;
}
哨兵
public int largestRectangleArea(int[] heights) {
int len = heights.length;
int maxArea = 0;
Stack<Integer> stack = new Stack<>();
int[] newHeights = new int[len + 2];
System.arraycopy(heights, 0, newHeights, 1, len);
heights = newHeights;
len += 2;
stack.push(0);
for (int i = 1; i < len; i++) {
while (heights[i] < heights[stack.peek()]) {
int height = heights[stack.pop()];
int width = i - stack.peek() - 1;
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
return maxArea;
}
最大矩形
給定一個僅包含 0
和 1
、大小為 rows x cols
的二維二進制矩陣么鹤,找出只包含 1
的最大矩形终娃,并返回其面積味廊。
示例 1:
輸入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
輸出:6
解釋:最大矩形如上圖所示蒸甜。
示例 2:
輸入:matrix = []
輸出:0
示例 3:
輸入:matrix = [["0"]]
輸出:0
示例 4:
輸入:matrix = [["1"]]
輸出:1
示例 5:
輸入:matrix = [["0","0"]]
輸出:0
方法一:暴力
遍歷每個點pos,以pos為矩形的右下角向左上尋找矩形余佛,不斷更新最大矩形
怎么找出這樣的矩陣呢柠新?如下圖,如果我們知道了以這個點結(jié)尾的連續(xù) 1 的個數(shù)的話辉巡,問題就變得簡單了恨憎。
以橙色的點為右下角,高度為 1:
高度為 2:
高度為 3:
public int maximalRectangle(char[][] matrix) {
if (matrix == null || matrix.length == 0) {
return 0;
}
int m = matrix.length, n = matrix[0].length;
// 每個點左邊(包括自己)連續(xù)1的數(shù)量
int[][] left = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
left[i][j] = (j > 0 ? left[i][j - 1] : 0) + 1;
}
}
}
int maxArea = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 在向上遍歷的過程中郊楣,記錄最小寬度
int minWidth = left[i][j];
for (int k = i; k >= 0; k--) {
// 如果遇到了0憔恳,就沒必要再向上找矩形了
if (matrix[k][j] == '0') {
break;
}
minWidth = Math.min(minWidth, left[k][j]);
maxArea = Math.max(maxArea, minWidth * (i - k + 1));
}
}
}
return maxArea;
}
時間復雜度O(m2n)
方法二:單調(diào)棧
參考上一題,記錄每一個點上邊(包括自己)連續(xù)一個個數(shù)净蚤,將這個個數(shù)看做高度钥组,再遍歷每一行,就算柱狀圖中最大的矩形
將之前的left數(shù)組改為pre數(shù)組
public int maximalRectangle(char[][] matrix) {
if (matrix == null || matrix.length == 0) {
return 0;
}
int m = matrix.length, n = matrix[0].length;
int[][] pre = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == '1') {
pre[i][j] = (i > 0 ? pre[i - 1][j] : 0) + 1;
}
}
}
int maxArea = 0;
for (int i = 0; i < m; i++) {
maxArea = Math.max(maxArea, largestRectangleArea(pre[i]));
}
return maxArea;
}
public int largestRectangleArea(int[] heights) {
int len = heights.length;
int maxArea = 0;
Stack<Integer> stack = new Stack<>();
int[] newHeights = new int[len + 2];
System.arraycopy(heights, 0, newHeights, 1, len);
heights = newHeights;
len += 2;
stack.push(0);
for (int i = 1; i < len; i++) {
while (heights[i] < heights[stack.peek()]) {
int height = heights[stack.pop()];
int width = i - stack.peek() - 1;
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
return maxArea;
}
時間復雜度O(mn)