在一個由 0 和 1 組成的二維矩陣內,找到只包含 1 的最大正方形,並返回其面積。java
示例:git
輸入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 輸出: 4
來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/maximal-square
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。github
本題可用BFS/廣度優先搜索或者dp動態規劃解決;算法
思路解析:對於matrix[i][j]爲'1'的位置,若其matrix[i+1][j]、matrix[i][j+1]、matrix[i+1][j+1]也都爲'1',那麼由matrix[i][j]能夠獲得一個邊長爲2的正方形;
按照整個邏輯遞歸BFS便可嘗試擴大正方形的邊長;數組
算法複雜度: m、n分別爲matrix的行和列網絡
思路解析:與思路1類似,可是dp是把matrix[i][j]爲'1'位置的左邊、上邊和左上位置的數據亞索至[i][j]位置;
對於matrix[i][j]爲'1'的位置能獲得的最大正方形的邊長爲dp[i][j]:ui
步驟:code
算法複雜度: m、n分別爲matrix的行和列遞歸
package leetcode; import java.util.ArrayDeque; import java.util.Deque; /** * @author ZhouJie * @date 2020年5月8日 下午5:06:45 * @Description: 221. 最大正方形 * */ public class LeetCode_0221 { } class Solution_0221 { /** * @author: ZhouJie * @date: 2020年5月8日 下午6:49:30 * @param: @param matrix * @param: @return * @return: int * @Description: 1-BFS; * */ public int maximalSquare_1(char[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return 0; } int row = matrix.length; int col = matrix[0].length; Deque<Integer> deque = new ArrayDeque<Integer>(); int size = 0, maxS = 0; // 右方、下方、右下方的方位 int[] dx = new int[] { 1, 0, 1 }; int[] dy = new int[] { 0, 1, 1 }; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { // 若當前是1則開始BFS if (matrix[i][j] == '1') { deque.clear(); // 保存座標,不使用數組,利用int整除和取模的特性存儲座標信息 deque.offer(i * col + j); // 初始變長爲1 int a = 1; boolean f = false; while (!deque.isEmpty()) { maxS = Math.max(a * a, maxS); size = deque.size(); while (size-- > 0) { Integer p = deque.poll(); int x = p / col; int y = p % col; int x0, y0; for (int k = 0; k < 3; k++) { x0 = x + dx[k]; y0 = y + dy[k]; // 當前位置的右方、下方、和右下方的位置也必須都是1才能擴大正方形的邊長,不然BFS到此爲止 if (x0 < row && y0 < col && matrix[x0][y0] == '1') { deque.offer(x0 * col + y0); } else { f = true; break; } } } if (f) { break; } a++; } } } } return maxS; } /** * @author: ZhouJie * @date: 2020年5月8日 下午6:49:40 * @param: @param matrix * @param: @return * @return: int * @Description: 2-dp動態規劃; * */ public int maximalSquare_2(char[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return 0; } int row = matrix.length; int col = matrix[0].length; // 記錄最大邊長 char max = '0'; // dp邏輯,第0行和第0列只須要記錄是否有1,從[1][1]開始dp,對於以後的[i][j]邏輯爲: // 若[i][j]不爲0,則: // dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1,dp[i][j] // dp[i][j]可能爲最大邊長,由於matrix自己就是dp所需的初始狀態,只是保存的爲char類型,須要轉int類型,因此能夠直接用matrix進行dp for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if ((i == 0 || j == 0)) { if (max == '0' && matrix[i][j] == '1') { max = '1'; } } else if (matrix[i][j] > '0') { matrix[i][j] = matrix[i][j - 1] < matrix[i - 1][j] ? matrix[i][j - 1] : matrix[i - 1][j]; matrix[i][j] = matrix[i][j] < matrix[i - 1][j - 1] ? matrix[i][j] : matrix[i - 1][j - 1]; matrix[i][j]++; max = max > matrix[i][j] ? max : matrix[i][j]; } } } return (max - '0') * (max - '0'); } }