面试题 17.23. 最大黑方阵c++题解
面试题 17.23. 最大黑方阵
给定一个方阵,其中每个单元(像素)非黑即白。设计一个算法,找出 4 条边皆为黑色像素的最大子方阵。
返回一个数组 [r, c, size] ,其中 r, c 分别代表子方阵左上角的行号和列号,size 是子方阵的边长。若有多个满足条件的子方阵,返回 r 最小的,若 r 相同,返回 c 最小的子方阵。若无满足条件的子方阵,返回空数组。
示例 1:
输入:
[
[1,0,1],
[0,0,1],
[0,0,1]
]
输出: [1,0,2]
解释: 输入中 0 代表黑色,1 代表白色,标粗的元素即为满足条件的最大子方阵
示例 2:
输入:
[
[0,1,1],
[1,0,1],
[1,1,0]
]
输出: [0,0,1]
提示:
matrix.length == matrix[0].length <= 200
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/max-black-square-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
// #include <iostream>
// #include<vector>
// using namespace std;
class Solution {
public:
vector<int> findSquare(vector<vector<int>>& matrix) {
if(!matrix.size() || !matrix[0].size()) return {};
int m =matrix.size();
int n = matrix[0].size();
vector<vector<int>> dp_up(m,vector<int>(n,0));
vector<vector<int>> dp_left(m,vector<int>(n,0));
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
if(!matrix[i][j]){
dp_up[i][j] = i ? dp_up[i-1][j] + 1 : 1;
dp_left[i][j] = j ? dp_left[i][j-1] + 1 : 1;
}
}
}
// for(int i=0;i<m;++i){
// for(int j=0;j<n;++j) {
// cout<< dp_left[i][j]<<","<<dp_up[i][j]<<" ";
// }
// cout <<endl;
// }
vector<int> ret = {-1,-1,-1};
for(int i = m-1;i>=0;--i)
for(int j=n-1;j>=0;--j){
int edge = min(dp_left[i][j],dp_up[i][j]);
if(edge < ret[2]) continue;
// cout<<"edge:"<<edge<<" ret:"<<ret[2]<<endl;
int x , y;
while(edge && edge >= ret[2]){
// cout<<"WA:"<<edge<<endl;
x = i - edge + 1;
y = j - edge + 1;
if(dp_up[i][y] >= edge && dp_left[x][j]>=edge){
if(edge > ret[2]){
ret[0] = x;
ret[1] = y;
ret[2] = edge;
}else if(edge == ret[2]){
if(ret[0] > x){
ret[0] = x;
ret[1] = y;
}else if(ret[0] == x && y < ret[1]){
ret[1] = y;
}
}
break;
}
edge--;
}
}
if(ret[2] == -1) return {};
return ret;
}
};
// int main() {
// cout << "test\n";
// vector<vector<int>> matrix = {
// {1,0,1},
// {0,0,1},
// {0,0,1}
// };
// Solution solution;
// auto a = solution.findSquare(matrix);
// for(int i = 0;i< 3;++i) cout <<a[i] << " ";
// return 0;
// }
注:代码中注释处的代码用于本地IDE测试
main函数可以自己设置数据,注释掉的for循环可以用于输出观察代码运行结果
题解思路
二维动态规划
规划完毕之后再进行回溯
DP时间复杂度O(mn),空间复杂度O(mn)
回溯的时间复杂度,较好的情况下O(mn)
较差的情况下 O(mn * edge)
edge = max(m,n),即O(mn^2)
或O(nm^2)