Problem: 1504. 统计全 1 子矩形
文章目录
- 思路
- 解题方法
- 复杂度
- Code
思路
这个问题可以通过压缩数组和单调栈的方法来解决。我们首先遍历矩阵,对于每一行,我们计算出每一列的高度(连续的1的数量)。然后,我们使用单调栈来计算以每个单元格为右下角的全1子矩形的数量。
解题方法
我们首先初始化一个高度数组,用于存储每一列的高度。然后,我们遍历矩阵,对于每一行,我们更新高度数组,并使用单调栈来计算以每个单元格为右下角的全1子矩形的数量。
单调栈的作用是帮助我们找到每个单元格左边和右边第一个高度小于它的单元格。这样,我们就可以计算出以每个单元格为右下角的全1子矩形的数量。
复杂度
时间复杂度:
O ( n m ) O(nm) O(nm),其中n和m分别是矩阵的行数和列数。我们需要遍历每个单元格,并在单调栈中进行操作。
空间复杂度:
O ( m ) O(m) O(m),我们需要使用一个高度数组和一个单调栈,它们的大小都与矩阵的列数m相等。
Code
class Solution {public static int MXAN = 151;public static int[] height = new int[MXAN];public static int[] stack = new int[MXAN];public static int r;public int numSubmat(int[][] mat) {int n = mat.length;int m = mat[0].length;int ans = 0;Arrays.fill(height, 0, m, 0);for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {height[j] = mat[i][j] == 0 ? 0 : height[j] + 1;}ans += countFromBottom(m);}return ans;}private static int countFromBottom(int m) {r = 0;int ans = 0;for (int i = 0, left, len, bottom; i < m; i++) {while (r > 0 && height[stack[r - 1]] >= height[i]) {int cur = stack[--r];if(height[cur] > height[i]) {left = r == 0 ? -1 : stack[r - 1];len = i - left - 1;bottom = Math.max(left == -1 ? 0 : height[left], height[i]);ans += (height[cur] - bottom) * (len * (len + 1) / 2);}}stack[r++] = i;}while(r > 0) {int cur = stack[--r];int left = r == 0 ? -1 : stack[r - 1];int len = m - left - 1;int down = left == -1 ? 0 : height[left];ans += (height[cur] - down) * (len * (len + 1) / 2); }return ans;}
}