问题描述
- 给定一个N*M的矩阵matrix, 在这个矩阵中, 只有0和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
问题分析
- 首先明确一个问题,便是如果枚举一个N*M的矩阵中的所有的子矩阵,时间复杂度为O(NM)*O(NM),因为一个矩形可由左上角与右下角决定,枚举左上角为O(NM),枚举左上角为O(NM)
那么如果枚举这个矩阵中所有的正方形呢?一个正方形可由左上角的点及其边长所决定,那么时间复杂度为O(NM)*min(N*M),因为边长最多有min(N,M)种情况。
- 所以对于该题,有两种解法:
- 方法1:枚举所有的正方形,然后检查四个边,所以当M=N时,这是O(N^4)时间复杂度
- 方法2:采用预处理矩阵的方法,同样也是枚举所有的正方形,但是判断该正方形是否符合规则是,是O(1)的时间复杂度,所以当M=N时,这是O(N^3)时间复杂度。
这是以空间换时间的做法。
那么如何预处理矩阵呢?
- 用与原矩阵同样大小的两个矩阵,一个为right,一个为down,right[i][j]表示m[i][j]的右边有多少个连续的1,包括自身;down[i][j]表示m[i][j]的下边有多少个连续的1,包括自身。从右到左,从下到上依次填好两个矩阵。
- 对于以[row,col]为左上角,length作为边长的正方形,要想四个边全为1,只有满足如下条件:row,col代表左上方的位置,要求左上方处下边最少有连续的length个1,右边最少有连续的length个1;[row + length - 1][col]代表左下角,要求该点右边最少有连续的length个1;[row][col + length - 1]代表右上角,要求该点下边最少有连续的length个1;这样便确立了四个边都符合规则。
经验教训:
- 预处理矩阵的技巧(举例:如果要求矩阵中某个矩形的和,那么应该如何预处理矩阵)
- 以当前点作为矩形右下角,原矩阵左上角作为新的左上角,求该矩阵的和,那么sum[][]便构造得到,根据sum矩阵,可以得到任意矩阵的和
- 关于该题的复杂度,以及如何更新两个矩阵
代码实现
package advanced_class_04;
public class MyCode_05_MaxOneBorderSize {
public