[Coding Made Simple] Maximum Subsquare surrounded by 'X'

Given a 2D matrix where every element is either ‘O’ or ‘X’, find the largest subsquare surrounded by ‘X’.

Examples:

Input: mat[N][N] = { {'X', 'O', 'X', 'X', 'X'},
                     {'X', 'X', 'X', 'X', 'X'},
                     {'X', 'X', 'O', 'X', 'O'},
                     {'X', 'X', 'X', 'X', 'X'},
                     {'X', 'X', 'X', 'O', 'O'},
                    };
Output: 3
The square submatrix starting at (1, 1) is the largest
submatrix surrounded by 'X'

Input: mat[M][N] = { {'X', 'O', 'X', 'X', 'X', 'X'},
                     {'X', 'O', 'X', 'X', 'O', 'X'},
                     {'X', 'X', 'X', 'O', 'O', 'X'},
                     {'X', 'X', 'X', 'X', 'X', 'X'},
                     {'X', 'X', 'X', 'O', 'X', 'O'},
                    };
Output: 4
The square submatrix starting at (0, 2) is the largest
submatrix surrounded by 'X'

 

Solution 1. O(N^4) runtime. 

Consider every square submatrix and check whether it is only surrounded by 'X'. 

There are O(N^3) square submatrices and each check takes O(N) time.

 

Solution 2. O(N^3) runtime, O(N^2) space, using dynamic programming

The idea is to create two auxiliary arrays hor[N][N] and ver[N][N].

The value stored in hor[i][j] is the number of horizontal continuous ‘X’ characters from left to right till matrix[i][j] in matrix[][].

Similarly, the value stored in ver[i][j] is the number of vertical continuous ‘X’ characters from top to bottom till matrix[i][j] in matrix[][]. 

 

Once we have filled values in hor[][] and ver[][], we start from the bottommost-rightmost corner of matrix and move toward the leftmost-topmost in row by row manner.

For every matrix[i][j] that is 'X', we compare the values of hor[i][j] and ver[i][j], and pick the smaller of two as we need a square. Let the smaller of two be ‘small’.

At this point, we are sure that there is a right vertical line and bottom horizontal line of length at least 'small'.

We find a bigger square if the following conditions are met.

1. small is bigger than the current max size length;

2. there is a left vertical line of length >= 'small';

3. there is a top horizontal line of length >= 'small'.

 

If the side length of 'small' does not generate a square, we try for small - 1. Repeat this until small is not bigger than max anymore.

 

 1 public class MaxSquareSubmatrix {
 2     public int getMaxSquareSubmatrixSideX(int[][] matrix) {
 3         if(matrix == null || matrix.length == 0 || matrix[0].length == 0) {
 4             return 0;
 5         }
 6         int[][] hor = new int[matrix.length][matrix[0].length];
 7         int[][] ver = new int[matrix.length][matrix[0].length];
 8         hor[0][0] = (matrix[0][0] == 'X' ? 1 : 0);
 9         ver[0][0] = (matrix[0][0] == 'X' ? 1 : 0);
10         for(int i = 1; i < matrix.length; i++) {
11             if(matrix[i][0] == 'O') {
12                 ver[i][0] = 0;
13                 hor[i][0] = 0;
14             }
15             else {
16                 ver[i][0] = 1 + ver[i - 1][0];
17                 hor[i][0] = 1;
18             }
19         }
20         for(int j = 1; j < matrix[0].length; j++) {
21             if(matrix[0][j] == 'O') {
22                 hor[0][j] = 0;
23                 ver[0][j] = 0;
24             }
25             else {
26                 hor[0][j] = 1 + hor[0][j - 1];
27                 ver[0][j] = 1;
28             }
29         }
30         for(int i = 1; i < matrix.length; i++) {
31             for(int j = 1; j < matrix[0].length; j++) {
32                 if(matrix[i][j] == 'O') {
33                     hor[i][j] = 0;
34                     ver[i][j] = 0;
35                 }
36                 else {
37                     hor[i][j] = 1 + hor[i][j - 1];
38                     ver[i][j] = 1 + ver[i - 1][j];
39                 }
40             }
41         }
42         int max = 0;
43         for(int i = matrix.length - 1; i >= 0; i--) {
44             for(int j = matrix[0].length - 1; j >= 0; j--) {
45                 if(matrix[i][j] == 'X') {
46                     int small = Math.min(hor[i][j], ver[i][j]);
47                     while(small > max) {
48                         if(ver[i][j - small + 1] >= small && hor[i - small + 1][j] >= small) {
49                             max = small;
50                             break;
51                         }
52                         else {
53                             small--;                        
54                         }
55                     }                    
56                 }
57             }
58         }
59         return max;
60     }
61 }

 

 

Related Problems 

Maximal Square

Maximal Square II

posted @ 2017-08-19 08:47  Review->Improve  阅读(368)  评论(0编辑  收藏  举报