Java算法–第四章–多维数组和矩阵(4)题目:边界为1的最大子方阵
给定一个N×N的矩阵matrix,在这个矩阵中,只有O和1两种值,返回边框全是1的最大正方形的边长长度。
例如∶
{0,1,1,1,1},
{0,1,0,0,1},
{0,1,0,0,1},
{0,1,1,1,1},
{0,1,0,1,1}
其中,边框全是1的最大正方形的大小是4*4,返回4
代码:
package matrix;
public class MaxSquare {
public static void main(String[] args) {
int[][] A = {
{ 0, 1, 1, 1, 1 },
{ 0, 1, 0, 0, 1 },
{ 0, 1, 0, 0, 1 },
{ 0, 1, 1, 1, 1 },
{ 0, 1, 0, 1, 1 }
};
// A = new int[][]{{0,0},{0,0}};
int res = solve(A);
System.out.println(res);
}
private static int solve(int[][] A) {
int N = A.length;
int n = N;
while (n > 0) {
for (int i = 0; i < N; i++) {
if (i + n > N)
break;
l3: for (int j = 0; j < N; j++) {
if (j + n > N)
break;
// 检查四条边
int r = i;
int c = j;
while (c < j + n) {
if (A[r][c++] == 0)
continue l3;
}
c--;
while (r < i + n) {
if (A[r++][c] == 0)
continue l3;
}
r--;
while (c >= j) {
if (A[r][c--] == 0)
continue l3;
}
c++;
while (r >= i) {
if (A[r--][c] == 0)
continue l3;
}
return n;
}
}
n--;
}
return n;
}
}
输出:
4
优化代码:
package matrix;
public class MaxSquare2 {
public static void main(String[] args) {
int[][] A = { { 0, 1, 1, 1, 1 }, { 0, 1, 0, 0, 1 }, { 0, 1, 0, 0, 1 }, { 0, 1, 1, 1, 1 }, { 0, 1, 0, 1, 1 } };
// A = new int[][]{{0,0},{0,0}};
help(A);
print(rec, A.length);
int res = solve(A);
System.out.println(res);
}
private static void print(int[][][] rec2, int N) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(" (" + rec[i][j][0] + "," + rec[i][j][1] + ") ");
}
System.out.println();
}
}
static int[][][] rec;
private static void help(int[][] A) {
int N = A.length;
rec = new int[N][N][2];
int row = N - 1;
for (int i = N - 1; i >= 0; i--) {
int value = A[row][i];
if (value == 1) {
if (i == N - 1) {
rec[row][i][0] = 1;
} else {
rec[row][i][0] = rec[row][i + 1][0] + 1;
}
rec[row][i][1] = 1;
}
}
row--;
for (int i = row; i >= 0; i--) {
for (int j = N - 1; j >= 0; j--) {
int value = A[i][j];
if (value == 1) {
if (j == N - 1) {
rec[i][j][0] = 1;
} else {
rec[i][j][0] = rec[i][j + 1][0] + 1;
}
rec[i][j][1] = rec[i + 1][j][1] + 1;
}
}
}
}
private static int solve(int[][] A) {
int N = A.length;
int n = N;
while (n > 0) {
for (int i = 0; i < N; i++) {
if (i + n > N)
break;
for (int j = 0; j < N; j++) {
if (j + n > N)
break;
if (check(i, j, n))
return n;
}
}
n--;
}
return n;
}
private static boolean check(int i, int j, int n) {
//左上角那个点往右数的1的数目要≥n
//左上角那个点往下数的1的数目要≥n
//右上角那个点往下数的1的数目要≥n
//左下角那个点往右数的1的数目要≥n
if(rec[i][j][0] >= n && rec[i][j][1] >= n && rec[i][j +n-1][1]>=n &&rec[i+n-1][j][0]>=n) {
return true;
}
return false;
}
}
优化输出:
(0,0) (4,5) (3,1) (2,1) (1,5)
(0,0) (1,4) (0,0) (0,0) (1,4)
(0,0) (1,3) (0,0) (0,0) (1,3)
(0,0) (4,2) (3,1) (2,2) (1,2)
(0,0) (1,1) (0,0) (2,1) (1,1)
4
P65