Date: 20200326
要坚持每天一篇好难。
1277. Count Square Submatrices with All Ones
Given a m * n matrix of ones and zeros, return how many square submatrices have all ones.
基本信息
Difficulty: Medium
Related Topics: Array, Dynamic Programming
v0.1.0
似曾相识的感觉,还是和prefix sum有关,和之前1314. Matrix Block Sum思路有些类似。
先计算(0,0)到(i,j)的矩形中有多少个正方形,存储在answer数组中.计算(i,j)的值,和(i-1, j),(i, j-1), (i-1, j-1)的值相关,如果matrix[i][j] == 0, answer[i][j] == 0。否则取matrix[i-1][j],matrix[i][j-1]), matrix[i-1][j-1]中最小值加上1。
然后再遍历一次数组。
answer[i][j] = answer[i][j] + answer[i-1][j] + answer[i][j-1] - answer[i-1][j-1]
当然如果是边边角角的格子要先判断一下(i-1, j),(i, j-1), (i-1, j-1)是不是超出了范围,超出了范围当0处理。
最后要的结果就是answer[answer.size()-1][answer[0].size()-1]的值。
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
vector<vector<int>> answer = matrix;
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[0].size(); j++) {
if (matrix[i][j] == 0) {
answer[i][j] = 0;
} else {
if(i > 0 && j > 0) {
int min_int = min(answer[i-1][j], answer[i][j-1]);
answer[i][j] = min(min_int, answer[i-1][j-1]) + 1;
} else {
answer[i][j] = 1;
}
}
}
}
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[0].size(); j++) {
if (i > 0) {
answer[i][j] += answer[i-1][j];
}
if (j > 0) {
answer[i][j] += answer[i][j-1];
}
if (i > 0 && j > 0) {
answer[i][j] -= answer[i-1][j-1];
}
}
}
return answer[answer.size()-1][answer[0].size()-1];
}
};
submission
Runtime: 76 ms, faster than 26.10% of C++ online submissions for Count Square Submatrices with All Ones. Memory Usage: 16.3 MB, less than 100.00% of C++ online submissions for Count Square Submatrices with All Ones.
反思
这个问题,我第一遍写的时候大体思路是没问题的,试了几个test case也都顺利通过了。但是提交的时候没有通过,是一个202*201的数组(我写了一个json文件,复制进去,然后用python看m和n分别是多少)。想到有四万多个格子想找到问题在哪里真是眼前一黑。
第一反应是写个一个python文件,随机生成matrix,结果试了十几个生成的都可以通过。然后就想能不能m和n取小一点的数(10以内或者5以内),然后生成所有可能情况。生成部分不难,比如2*3的数组可以看成1*6的一维数组,每一位都可以是1或者0,相当于是0到2^6-1的数字的二进制表达(000000相当于6个元素是0,111111相当于6个元素是1)。
然而想想生成了比如64个例子依次复制到leetcode网站然后等结果就头大。研究了一下好像leetcode没有提供api(不禁让我想问vs code的leetcode插件是如何实现的)。放弃了这条路。
还是要从出错的202*201数组找问题。
结果我就开始用二分法分割数组,找到自数组中出错的部分。用了不到10次吧,就找到了问题所在。
其中行数为199-202,列数为162-166的部分是这样的[[0, 1, 1, 0, 0], [0, 1, 1, 1, 1], [0, 0, 1, 1, 0]]
我一开始在通过matrix[i-1][j],matrix[i][j-1]), matrix[i-1][j-1]计算answer[i][j]的值的时候是“如果matrix[i-1][j],matrix[i][j-1]),answer[i][j] = matrix[i-1][j-1]+1”,黄色的那一格结果就是3。但实际上应该取matrix[i-1][j],matrix[i][j-1]), matrix[i-1][j-1]中最小值加上1。
所以这里答案应该是10,我一开始的方法算出来是11。