1504. 统计全 1 子矩形
给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。
示例 1:
输入:mat = [[1,0,1],
[1,1,0],
[1,1,0]]
输出:13
解释:
有 6 个 1x1 的矩形。
有 2 个 1x2 的矩形。
有 3 个 2x1 的矩形。
有 1 个 2x2 的矩形。
有 1 个 3x1 的矩形。
矩形数目总共 = 6 + 2 + 3 + 1 + 1 = 13 。
示例 2:
输入:mat = [[0,1,1,0],
[0,1,1,1],
[1,1,1,0]]
输出:24
解释:
有 8 个 1x1 的子矩形。
有 5 个 1x2 的子矩形。
有 2 个 1x3 的子矩形。
有 4 个 2x1 的子矩形。
有 2 个 2x2 的子矩形。
有 2 个 3x1 的子矩形。
有 1 个 3x2 的子矩形。
矩形数目总共 = 8 + 5 + 2 + 4 + 2 + 2 + 1 = 24 。
思路1.0(已看题解)
将统计矩阵中全1子矩阵分为两个步骤:(1)统计每一行的全1子矩阵
(2)以压缩的方法从上往下统计剩下的全1子矩阵
图中是以列数r=2来进行压缩,这种按位与的压缩方法,可以使压缩后的1来映射压缩前的子矩阵是否是2x1,而两个连续的压缩后的1,即两个连续的2x1子矩阵,也就是一个2x2矩阵啦。然后只要再通过第(1)步中,统计每行的全1子矩阵的方法,然后再重复统计n=[2:4]的情况,就欧了。
代码1.0(AC):
class Solution {
public:
int numSubmat(vector<vector<int>>& mat) {
int row = mat.size();
int col = mat[0].size();
int tol = 0;
for (int k = 0; k <row; k++)
{
//统计
for (int i = k; i < row; ++i)
{
int sum = 0;
for (int j = 0; j < col; ++j)
{
if (mat[i][j] == 0) sum = 0;
else sum += mat[i][j];
tol += sum;
}
}
//压缩
for (int i = row - 1; i > k; --i)
{
for (int j = 0; j < col; ++j)
{
mat[i][j] = mat[i][j] & mat[i - 1][j];
}
}
}
return tol;
}
};
矩阵压缩这个方法很好理解,但是复杂度有点高,要多次遍历矩阵,而且好像没用到动态规划的思想,自己一上来一点思路都没有就是因为找不到用上动态规划的方法(找不到最优子结构)。