I have a matrix of size N*M filled with 0's and 1's. For each query K, I have to answer the maximum sized square sub-matrix in which minimum(number of 1's, number of 0's)=k where 1<=K<=10^9. For example consider the matrix of size 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
I understood that for k=1, the sub-matrix (1,1) to (7,7) works for k=2, the largest square sub-matrix is the original matrix itself. For k=1, we have to get all the 7*7 square sub-matrix. Find their min(no. of 1's,no. of 0's) and then get the minimum of all those as the answer.
I am not able to generate all the pairs of square sub-matrix. Can anyone help me in achieving that? Also, if any shorter way is available, that will be good as well because this takes very much time.
Is this an interview question? This problem is very similar to that of the maximum submatrix sum (https://www.geeksforgeeks.org/maximum-sum-rectangle-in-a-2d-matrix-dp-27/), whose DP solution you should be able to adapt for this.
EDIT:
The following is O(n^3) time O(n^2) memory The import piece to realize is that the area D = Entire Area - 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));
}