最大尺寸方子矩阵
Maximum sized square sub-matrix
我有一个大小为 N*M 的矩阵,其中填充了 0 和 1。
对于每个查询 K,我必须回答最大尺寸的方形子矩阵,其中最小值(1 的数量,0 的数量)=k,其中 1<=K<=10^9。例如考虑大小为 8*8 的矩阵:
10000000
01000000
00000000
00000000
00000000
00000000
00000000
00000000
k= 1 answer= 7
k=2 answer= 8
k=0 answer= 6
k=1001 answer= 8
我明白了,对于k=1,子矩阵(1,1)到(7,7)对k=2起作用,最大方子矩阵就是原矩阵本身。
对于 k=1,我们必须得到所有的 7*7 方阵子矩阵。找到他们的最小值(1 的个数,0 的个数),然后得到所有这些中的最小值作为答案。
我无法生成所有的方形子矩阵对。谁能帮助我实现这一目标?另外,如果有任何更短的方法可用,那也很好,因为这需要很多时间。
这是面试题吗?这个问题与最大子矩阵和(https://www.geeksforgeeks.org/maximum-sum-rectangle-in-a-2d-matrix-dp-27/)的问题非常相似,你应该能够适应它的DP解决方案。
编辑:
下面是O(n^3)次O(n^2)次内存
要实现的导入部分是区域 D = 整个区域 - B - C + A
| A B |
| C D |
#include <stdlib.h>
#include <stdio.h>
int **create_dp(int **matrix, int **dp, int row, int col) {
dp[0][0] = matrix[0][0];
for (int i = 1; i < row; ++i)
dp[i][0] = matrix[i][0] + dp[i - 1][0];
for (int j = 1; j < col; ++j)
dp[0][j] = matrix[0][j] + dp[0][j - 1];
for (int i = 1; i < row; ++i)
for (int j = 1; j < col; ++j)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + matrix[i][j] - dp[i - 1][j - 1];
}
int min(int x, int y) {
if (x > y) return y;
return x;
}
int max_square_submatrix(int **matrix, int row, int col, int query) {
// the value dp[i][j] is the sum of all values in matrix up to i, j
// i.e. dp[1][1] = matrix[0][0] + matrix[1][0] + matrix[0][1] + matrix[1][1]
int **dp = malloc(sizeof(int*) * row);
for (int i = 0; i < row; ++i) dp[i] = malloc(sizeof(int) * col);
create_dp(matrix, dp, row, col);
int global_max_size = 0;
// go through all squares in matrix
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
// begin creating square matrices
// this is the largest size a square matrix could have
int max_size = min(row - i, col - j) - 1;
for (; max_size >= 0; --max_size) {
// you need to see above diagram in order to visualize this step
int num_ones = dp[i + max_size][j + max_size];
if (i > 0 && j > 0)
num_ones += -dp[i + max_size][j - 1] - dp[i - 1][j + max_size] + dp[i - 1][j - 1];
else if (j > 0)
num_ones += -dp[i + max_size][j - 1];
else if (i > 0)
num_ones += -dp[i - 1][j + max_size];
if (num_ones <= query) break;
}
if (global_max_size < max_size + 1) global_max_size = max_size + 1;
}
}
// free dp memory here
return global_max_size;
}
int main() {
#define N 8
#define M 8
int **matrix = malloc(sizeof(int*) * N);
for (int i = 0; i < N; ++i) matrix[i] = malloc(sizeof(int) * M);
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
matrix[i][j] = 0;
matrix[0][0] = matrix[1][1] = 1;
printf("%d\n", max_square_submatrix(matrix, 8, 8, 1));
printf("%d\n", max_square_submatrix(matrix, 8, 8, 2));
printf("%d\n", max_square_submatrix(matrix, 8, 8, 0));
printf("%d\n", max_square_submatrix(matrix, 8, 8, 1001));
}
我有一个大小为 N*M 的矩阵,其中填充了 0 和 1。 对于每个查询 K,我必须回答最大尺寸的方形子矩阵,其中最小值(1 的数量,0 的数量)=k,其中 1<=K<=10^9。例如考虑大小为 8*8 的矩阵:
10000000
01000000
00000000
00000000
00000000
00000000
00000000
00000000
k= 1 answer= 7
k=2 answer= 8
k=0 answer= 6
k=1001 answer= 8
我明白了,对于k=1,子矩阵(1,1)到(7,7)对k=2起作用,最大方子矩阵就是原矩阵本身。 对于 k=1,我们必须得到所有的 7*7 方阵子矩阵。找到他们的最小值(1 的个数,0 的个数),然后得到所有这些中的最小值作为答案。
我无法生成所有的方形子矩阵对。谁能帮助我实现这一目标?另外,如果有任何更短的方法可用,那也很好,因为这需要很多时间。
这是面试题吗?这个问题与最大子矩阵和(https://www.geeksforgeeks.org/maximum-sum-rectangle-in-a-2d-matrix-dp-27/)的问题非常相似,你应该能够适应它的DP解决方案。
编辑:
下面是O(n^3)次O(n^2)次内存 要实现的导入部分是区域 D = 整个区域 - B - C + A
| A B |
| C D |
#include <stdlib.h>
#include <stdio.h>
int **create_dp(int **matrix, int **dp, int row, int col) {
dp[0][0] = matrix[0][0];
for (int i = 1; i < row; ++i)
dp[i][0] = matrix[i][0] + dp[i - 1][0];
for (int j = 1; j < col; ++j)
dp[0][j] = matrix[0][j] + dp[0][j - 1];
for (int i = 1; i < row; ++i)
for (int j = 1; j < col; ++j)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + matrix[i][j] - dp[i - 1][j - 1];
}
int min(int x, int y) {
if (x > y) return y;
return x;
}
int max_square_submatrix(int **matrix, int row, int col, int query) {
// the value dp[i][j] is the sum of all values in matrix up to i, j
// i.e. dp[1][1] = matrix[0][0] + matrix[1][0] + matrix[0][1] + matrix[1][1]
int **dp = malloc(sizeof(int*) * row);
for (int i = 0; i < row; ++i) dp[i] = malloc(sizeof(int) * col);
create_dp(matrix, dp, row, col);
int global_max_size = 0;
// go through all squares in matrix
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
// begin creating square matrices
// this is the largest size a square matrix could have
int max_size = min(row - i, col - j) - 1;
for (; max_size >= 0; --max_size) {
// you need to see above diagram in order to visualize this step
int num_ones = dp[i + max_size][j + max_size];
if (i > 0 && j > 0)
num_ones += -dp[i + max_size][j - 1] - dp[i - 1][j + max_size] + dp[i - 1][j - 1];
else if (j > 0)
num_ones += -dp[i + max_size][j - 1];
else if (i > 0)
num_ones += -dp[i - 1][j + max_size];
if (num_ones <= query) break;
}
if (global_max_size < max_size + 1) global_max_size = max_size + 1;
}
}
// free dp memory here
return global_max_size;
}
int main() {
#define N 8
#define M 8
int **matrix = malloc(sizeof(int*) * N);
for (int i = 0; i < N; ++i) matrix[i] = malloc(sizeof(int) * M);
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
matrix[i][j] = 0;
matrix[0][0] = matrix[1][1] = 1;
printf("%d\n", max_square_submatrix(matrix, 8, 8, 1));
printf("%d\n", max_square_submatrix(matrix, 8, 8, 2));
printf("%d\n", max_square_submatrix(matrix, 8, 8, 0));
printf("%d\n", max_square_submatrix(matrix, 8, 8, 1001));
}