221. Maximal Square
2016-07-16 18:01
302 查看
题目:最大正方形
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and return its area.
For example, given the following matrix:
Return 4.
题意:
给定一个二维的由1和0字符填充的二进制矩阵,找到只包含1的最大的正方形,返回其面积。
思路一:
维护一个动态二维数组size,二维数组size的大小与给定的矩阵大小相同,初始化的时候将该矩阵初始化为0。二维数组的每一个数组值代表二维矩阵中直到下标位置时,最大正方形的边长是多少。首先利用二维矩阵将第一行与第一列对应的最大正方形边长存储在对应的二维数组中。之后从matrix[1][1]元素开始,只有当该元素左边元素,上边元素,左上面元素均为1字符时,最大正方形边长才能加1.即,在对应的size二维数组中,该元素的左边元素,上边元素,左上面元素三个值中最小的一个值才能决定当前元素所对应的值为多少。只有三个都为最大的,才能使最大正方形边长加1.
代码:C++版:20ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int m = matrix.size();
if (!m) return 0;
int n = matrix[0].size();
vector<vector<int>> size(m, vector<int>(n, 0));//存储每个元素处对应的最大正方形边长
int maxsize = 0;
for (int j=0; j<n; j++) {//计算第一行元素对应的正方形边长
size[0][j] = matrix[0][j] - '0';
maxsize = max(maxsize, size[0][j]);
}
for (int i=1; i<m; i++) {//计算第一列元素对应的正方形边长
size[i][0] = matrix[i][0] - '0';
maxsize = max(maxsize, size[i][0]);
}
for (int i=1; i<m; i++) {
for (int j=1; j<n; j++) {
if (matrix[i][j] == '1') {
//计算每个元素对应位置的最大正方形边长
size[i][j] = min(size[i-1][j-1], min(size[i-1][j], size[i][j-1])) + 1;
maxsize = max(maxsize, size[i][j]);
}
}
}
return maxsize * maxsize;
}
};
思路二:
优化以上代码的空间复杂度。经上面分析可得,要更新size[i][j],只需要知道size[i][j - 1], size[i - 1][j - 1]和 size[i - 1][j]这三个位置的值即可,所以只需要两个m大小的整数数组即可。
代码:C++版:12ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int m = matrix.size();
if (!m) return 0;
int n = matrix[0].size();
vector<int> pre(m, 0);
vector<int> cur(m, 0);
int maxsize = 0;
for (int i=0; i<m; i++) { //处理第一列
pre[i] = matrix[i][0] - '0';
maxsize = max(maxsize, pre[i]);
}
for (int j=1; j<n; j++) {
cur[0] = matrix[0][j] - '0'; //处理后面列中的第一个元素
maxsize = max(maxsize, cur[0]);
for (int i=1; i<m; i++) {
if (matrix[i][j] == '1') {
cur[i] = min(cur[i-1], min(pre[i-1], pre[i])) + 1;
maxsize = max(maxsize, cur[i]);
}
}
swap(pre, cur);
fill(cur.begin(), cur.end(), 0);
}
return maxsize * maxsize;
}
};
思路三:
继续对思路二代码的空间复杂度进行优化,只需要维持一个m+1的数组即可,利用一个常数变量存储左上角的元素,利用存储的这些信息即可更新当前的数。
代码:C++版:12ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.empty()) return 0;
int m = matrix.size(), n = matrix[0].size();
vector<int> dp(m+1, 0);
int maxsize = 0, pre = 0;
for (int j=0; j<n; j++) {
for (int i=1; i<=m; i++) {
int temp = dp[i];
if (matrix[i-1][j] == '1') {
dp[i] = min(dp[i], min(dp[i-1], pre)) + 1;
maxsize = max(maxsize, dp[i]);
} else dp[i] = 0;
pre = temp;
}
}
return maxsize * maxsize;
}
};
思路四:
把数组中的每一个点都当成正方形的左顶点来向右下扫描来寻找最大正方形。扫描步骤为,确定了左顶点后,再往下扫描的时候,正方形的竖边长就确定了,只需要找到横边即可,这时使用直方图原理,使其累加值能反映出上面的值是否全为1字符。
代码:C++版:252ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int res = 0;
for (int i=0; i<matrix.size(); ++i) {
vector<int> v(matrix[i].size(), 0);
for (int j=i; j<matrix.size(); ++j) { //向下扫描
for (int k=0; k<matrix[j].size(); ++k) { //向右扫描
if (matrix[j][k] == '1') ++v[k];
}
res = max(res, getSquareArea(v, j-i+1));
}
}
return res;
}
int getSquareArea(vector<int> &v, int k) { //计算每次正方形的面积
if (v.size() < k) return 0;
int count = 0;
for (int i=0; i<v.size(); ++i) {
if (v[i] != k) count = 0;
else ++count;
if (count == k) return k*k;
}
return 0;
}
};
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and return its area.
For example, given the following matrix:
1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0
Return 4.
题意:
给定一个二维的由1和0字符填充的二进制矩阵,找到只包含1的最大的正方形,返回其面积。
思路一:
维护一个动态二维数组size,二维数组size的大小与给定的矩阵大小相同,初始化的时候将该矩阵初始化为0。二维数组的每一个数组值代表二维矩阵中直到下标位置时,最大正方形的边长是多少。首先利用二维矩阵将第一行与第一列对应的最大正方形边长存储在对应的二维数组中。之后从matrix[1][1]元素开始,只有当该元素左边元素,上边元素,左上面元素均为1字符时,最大正方形边长才能加1.即,在对应的size二维数组中,该元素的左边元素,上边元素,左上面元素三个值中最小的一个值才能决定当前元素所对应的值为多少。只有三个都为最大的,才能使最大正方形边长加1.
代码:C++版:20ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int m = matrix.size();
if (!m) return 0;
int n = matrix[0].size();
vector<vector<int>> size(m, vector<int>(n, 0));//存储每个元素处对应的最大正方形边长
int maxsize = 0;
for (int j=0; j<n; j++) {//计算第一行元素对应的正方形边长
size[0][j] = matrix[0][j] - '0';
maxsize = max(maxsize, size[0][j]);
}
for (int i=1; i<m; i++) {//计算第一列元素对应的正方形边长
size[i][0] = matrix[i][0] - '0';
maxsize = max(maxsize, size[i][0]);
}
for (int i=1; i<m; i++) {
for (int j=1; j<n; j++) {
if (matrix[i][j] == '1') {
//计算每个元素对应位置的最大正方形边长
size[i][j] = min(size[i-1][j-1], min(size[i-1][j], size[i][j-1])) + 1;
maxsize = max(maxsize, size[i][j]);
}
}
}
return maxsize * maxsize;
}
};
思路二:
优化以上代码的空间复杂度。经上面分析可得,要更新size[i][j],只需要知道size[i][j - 1], size[i - 1][j - 1]和 size[i - 1][j]这三个位置的值即可,所以只需要两个m大小的整数数组即可。
代码:C++版:12ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int m = matrix.size();
if (!m) return 0;
int n = matrix[0].size();
vector<int> pre(m, 0);
vector<int> cur(m, 0);
int maxsize = 0;
for (int i=0; i<m; i++) { //处理第一列
pre[i] = matrix[i][0] - '0';
maxsize = max(maxsize, pre[i]);
}
for (int j=1; j<n; j++) {
cur[0] = matrix[0][j] - '0'; //处理后面列中的第一个元素
maxsize = max(maxsize, cur[0]);
for (int i=1; i<m; i++) {
if (matrix[i][j] == '1') {
cur[i] = min(cur[i-1], min(pre[i-1], pre[i])) + 1;
maxsize = max(maxsize, cur[i]);
}
}
swap(pre, cur);
fill(cur.begin(), cur.end(), 0);
}
return maxsize * maxsize;
}
};
思路三:
继续对思路二代码的空间复杂度进行优化,只需要维持一个m+1的数组即可,利用一个常数变量存储左上角的元素,利用存储的这些信息即可更新当前的数。
代码:C++版:12ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.empty()) return 0;
int m = matrix.size(), n = matrix[0].size();
vector<int> dp(m+1, 0);
int maxsize = 0, pre = 0;
for (int j=0; j<n; j++) {
for (int i=1; i<=m; i++) {
int temp = dp[i];
if (matrix[i-1][j] == '1') {
dp[i] = min(dp[i], min(dp[i-1], pre)) + 1;
maxsize = max(maxsize, dp[i]);
} else dp[i] = 0;
pre = temp;
}
}
return maxsize * maxsize;
}
};
思路四:
把数组中的每一个点都当成正方形的左顶点来向右下扫描来寻找最大正方形。扫描步骤为,确定了左顶点后,再往下扫描的时候,正方形的竖边长就确定了,只需要找到横边即可,这时使用直方图原理,使其累加值能反映出上面的值是否全为1字符。
代码:C++版:252ms
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
int res = 0;
for (int i=0; i<matrix.size(); ++i) {
vector<int> v(matrix[i].size(), 0);
for (int j=i; j<matrix.size(); ++j) { //向下扫描
for (int k=0; k<matrix[j].size(); ++k) { //向右扫描
if (matrix[j][k] == '1') ++v[k];
}
res = max(res, getSquareArea(v, j-i+1));
}
}
return res;
}
int getSquareArea(vector<int> &v, int k) { //计算每次正方形的面积
if (v.size() < k) return 0;
int count = 0;
for (int i=0; i<v.size(); ++i) {
if (v[i] != k) count = 0;
else ++count;
if (count == k) return k*k;
}
return 0;
}
};
相关文章推荐
- 【spring 3】AOP:静态代理
- webpack快速入门和实战
- kruskal算法求最小生成树(jungle roads的kruskal解法)
- 晶/陶振不起振及使用注意事项
- 慕课网实战—《用组件方式开发 Web App全站 》笔记七-饼图和环图组件开发
- 以后的博客可能会偏向游戏开发方向
- selenium2使用记录
- telnet时显示:允许更多到 telnet 服务器的连接。请稍候再试
- 使用贝赛尔曲线实现仿360拖动安仔清理动画
- overwrite在hive内部表及外部表特性
- POJ 1200 Crazy Search
- pager 命令
- LTS版本的解析
- [LeetCode] 13. Roman to Integer
- 线性表
- node package有两种依赖
- jQuery学习之jQuery Ajax用法详解
- Android入门——数据存储之SharedPreferences详解与应用
- [C++]高效使用关联容器的一些建议
- django haystack update_index 实现自动化 同步