题目描述:给定一个N✖N的矩阵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。
这道题我之前还写过一篇采用暴力搜索法来解决的,但是时间复杂度比较大O(N^4)可能会超时,没看过的小伙伴可以看下:暴力搜索版
此处我们先对这个矩阵进行预处理,有点类似于动态规划,思路就是新建一个N✖N✖2的三维数组,其中规定,每一个元素如果是1,那么就看这个元素的右侧和下侧分别有多少个连续的1,然后利用三维数组的最后一维的0号位置来存右侧的(包括本身)1的个数,最后一维的1号位置来存下侧的(包括本身)的1的个数。这里有个小技巧就是应当从最后一行的最后一个元素(即[N-1][N-1])来向前进行初始化。然后我们再检查这个辅助三维数组是否满足某一个特定的阶数(例如n阶)即可——检查的方法也很简单,只需要看当前元素(以此为边框的左上顶点)的右侧和下侧是否至少有n个1,右顶点的下侧是否至少有n个1,以及左下顶点的右侧是否至少有n个1。
看下代码吧:
#include<iostream>
#define N 5
using namespace std;
int solve(int matrix[][N]){
int helper[N][N][2]={0}; //申请一个辅助数组空间
int r = N-1,c = N-1; //r,c为要预处理的当前位置,从最后一个元素开始
//先对最后一行初始化
for(;c>=0;c--){
if(matrix[r][c] == 1){ //前提得是1
if(c == N-1){ //如果是最后一列
helper[r][c][0] = 1;
helper[r][c][1] = 1;
}
else{
helper[r][c][0] = helper[r][c+1][0] + 1;
helper[r][c][1] = 1;
}
}
}
//再对前面的预处理
//防止越界
if(N-2 >= 0){
r = N-2;
for(;r>=0;r--){
for(c = N-1;c>=0;c--){
if(matrix[r][c] == 1){ //前提得是1
if(c == N-1){ //如果是最后一列
helper[r][c][0] = 1;
helper[r][c][1] = helper[r+1][c][1] + 1;
}
else{
helper[r][c][0] = helper[r][c+1][0] + 1;
helper[r][c][1] = helper[r+1][c][1] + 1;
}
}
}
}
}
int n = 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;
//check一下左上顶点的右边和下边,右上顶点的下边以及左下顶点的右边是否满足n阶
if(helper[i][j][0] >= n && helper[i][j][1] >= n && helper[i][j+n-1][1] >= n && helper[i+n-1][j][0] >= n){
return n;
}
}
}
n--;
}
return n; //全为0的情况
}
int main(){
int matrix[N][N] = {
{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}
};
int res = solve(matrix);
cout<<"result: "<<res;
}
运行结果也是一样的:
也欢迎大家测试一下有没有漏洞,我测的时候除了matrix是空的有点小问题以外,其他都正常,如果有问题也请慷慨指出哦。