程序员面试金典——最大子方阵问题:找到四条边颜色相同的最大子方阵

来源:互联网 发布:嫖相 知乎 编辑:程序博客网 时间:2024/06/06 07:35

问题描述:

有一个方阵,其中每个单元(像素)非黑即白(非0即1),请设计一个高效算法,找到四条边颜色相同的最大子方阵。

给定一个01方阵mat,同时给定方阵的边长n,请返回最大子方阵的边长。保证方阵边长小于等于100。

测试样例:
[[1,1,1],[1,0,1],[1,1,1]],3
返回:3
解决思路:

采用动态规划思想,用两个辅助数组left和up,left[i][j]表示连续紧挨着mat[i][j]的左边有多少个与mat[i][j]相同的元素数,如果没有则为1,即只有自己相等。同理up[i][j]表示连续紧挨着mat[i][j]的上边有多少个与mat[i][j]相同的元素数,如果没有则为1。

然后依次判断数组的元素左边和右边元素与其相等,这个元素有可能是满足条件的正方形的右下角顶点,然后进行详细的判断。

class SubMatrix {public:int maxSubMatrix(vector<vector<int> > mat, int n) {//采用动态规划思想,用两个辅助数组left和up,left[i][j]表示连续紧挨着mat[i][j]的左边有多少个与mat[i][j]相同的元素数,如果没有则为1,即只有自己相等。//同理up[i][j]表示连续紧挨着mat[i][j]的上边有多少个与mat[i][j]相同的元素数,如果没有则为1。int maxlen = 1;vector <vector<int>> left(n),up(n);for (int i = 0; i < n; ++i){left[i].resize(n);up[i].resize(n);}initial(mat, left, up, n);for (int i = 1; i < n; ++i){for (int j = 1; j < n; ++j){if (mat[i][j] == mat[i][j - 1] && mat[i][j] == mat[i - 1][j])//该元素左边和右边元素与其相等,这个元素有可能是满足条件的正方形的右下角顶点{left[i][j] = left[i][j - 1] + 1;up[i][j] = up[i - 1][j] + 1;int len = left[i][j] < up[i][j] ? left[i][j] : up[i][j];for (int k = len - 1; k > 0 && k + 1 > maxlen; --k){//此处计算maxlen,依次判断以mat[i][j]为右下顶点的正方形边长依次为len到maxlen+1是否可行,可行则更新maxlen,不用再减1计算了,否则保持不变。if (left[i - k][j] > k&&up[i][j - k] > k){maxlen = k + 1;break;}}}else{if (mat[i][j] == mat[i][j - 1])left[i][j] = left[i][j - 1] + 1;elseleft[i][j] = 1;if (mat[i][j] == mat[i - 1][j])up[i][j] = up[i - 1][j] + 1;elseup[i][j] = 1;}}}return maxlen;}private:void initial(vector<vector<int> > &mat, vector<vector<int> > &left, vector<vector<int> > &up, int n){for (int i = 0; i < n; ++i){left[i][0] = 1;up[0][i] = 1;}for (int i = 1; i < n; ++i){if (mat[0][i] == mat[0][i - 1])left[0][i] = left[0][i - 1] + 1;elseleft[0][i] = 1;if (mat[i][0] == mat[i - 1][0])up[i][0] = up[i - 1][0] + 1;elseup[i][0] = 1;}}};

阅读全文
0 0