PigyChan

it2026-04-20  2

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; } };

矩阵压缩这个方法很好理解,但是复杂度有点高,要多次遍历矩阵,而且好像没用到动态规划的思想,自己一上来一点思路都没有就是因为找不到用上动态规划的方法(找不到最优子结构)。

最新回复(0)