01二維矩陣中最大全為1的正方形maxSquare
阿新 • • 發佈:2019-02-18
在一個二維01矩陣中找到全為1的最大正方形
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Solution1:該題目可以採用暴力搜尋的方式獲取結果,依次以矩陣中每一個點為正方形的左上角進行遍歷並篩選出最大邊長的正方形,具體程式碼如下:
public static int solution(int[][] matrix) {
if (matrix.length==0||matrix[0].length==0) {
return 0;
}
int M = matrix.length, N = matrix[0 ].length, res = 0;
for (int i=0 ;i<M; i++) {
for (int j=0; j<N; j++) {
if (matrix[i][j] == 0)
continue;
else {
int scanRes = scan(matrix, i, j, M, N);
if (scanRes>=res)
res = scanRes;
}
}
}
return res;
}
public static int scan(int[][] matrix, int i, int j, int M, int N) {
int S = (M-i)<=(N-j)?(M-i):(N-j);
for (int k=S; k>=2; k--) {
boolean flag = true;
a:for (int l=i; l<(k+i); l++) {
b:for (int m=j; m<(k+j); m++) {
if (matrix[l][m]==0) {
flag =false;
break a;
}
}
}
if (!flag) {
continue;
} else {
return k;
}
}
return 1;
}
很顯然暴力搜尋演算法時間複雜度遠遠超過預期數量級,因此可以採用動態規劃來解決該問題
Solution2: 我們以矩陣中每一個點作為正方形右下角點來處理,而以該點為右下角點的最大邊長最多比以它的左方、上方和左上方為右下角的正方形邊長多1,所以這時只能取另外三個正方形中最小的正方形邊長+1。用d[i][j]表示以i,j座標為右下角的正方形最大邊。則有狀態轉移方程:dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1])) + 1,具體程式碼如下:
public static int maxSquare(int[][] matrix) {
if (matrix.length==0||matrix[0].length==0) {
return 0;
}
int M = matrix.length, N = matrix[0].length, res = 0;
int[][] dp = new int[M][N];
for (int i=0; i<M; i++) {
if (matrix[i][0] == 1) {
dp[i][0] = 1;
res = 1;
}
}
for (int j=0; j<N; j++) {
if (matrix[0][j] == 1) {
dp[0][j] = 1;
res = 1;
}
}
for (int i=1; i<M; i++) {
for (int j=1; j<N; j++) {
if (matrix[i][j] == 1) {
dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1])) + 1;
}
res = max(res, dp[i][j]);
}
}
return res;
}
可以看出S2採用動態規劃方法正向依次利用之前儲存的狀態計算出下一個狀態值,從而避免了重複計算,大大提升了時間複雜度。相比於S1方法無論從時間複雜度和程式碼可讀性都有很大提升。