统计全为 1 的正方形子矩阵
难度:
标签:
题目描述
代码结果
运行时间: 98 ms, 内存: 18.6 MB
/*
* Solution Explanation:
* Java Streams are not particularly suited for this type of dynamic programming problem because the solution requires updates in place and dependence on previous values. However, we can still use some functional programming concepts.
*/
import java.util.stream.IntStream;
public class Solution {
public int countSquares(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] dp = new int[m][n];
int[] count = {0}; // Use an array to allow lambda to modify
IntStream.range(0, m).forEach(i -> {
IntStream.range(0, n).forEach(j -> {
if (matrix[i][j] == 1) {
if (i == 0 || j == 0) {
dp[i][j] = 1;
} else {
dp[i][j] = Math.min(Math.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
}
count[0] += dp[i][j];
}
});
});
return count[0];
}
}
解释
方法:
本题解采用动态规划的方法来解决问题。我们设一个与输入矩阵相同大小的DP表,dp[i][j]表示以(i, j)为右下角的正方形的最大边长。对于每个1在矩阵中的位置,如果它是第一行或第一列的一部分,它只能形成边长为1的正方形(即本身)。对于其他位置,如果matrix[i][j]是1,dp[i][j]将基于其左方(dp[i][j-1])、上方(dp[i-1][j])以及左上方(dp[i-1][j-1])的dp值,取这三个值中的最小值然后加1。这确保了只计算完全由1组成的正方形。最后,将所有dp[i][j]的值累加,即得到所有可能的正方形数量。
时间复杂度:
O(m*n)
空间复杂度:
O(m*n)
代码细节讲解
🦆
为什么dp数组的初始化都是0,而不是直接将矩阵的值复制过来?
▷🦆
在动态规划中,为什么选择取左方、上方和左上方三个dp值的最小值然后加1来更新dp[i][j]?这样做的数学逻辑是什么?
▷🦆
题解中提到如果matrix[i][j]是1且位于第一行或第一列,dp[i][j]直接设置为1。请问这种处理对结果的正确性有什么影响?
▷🦆
在实现中,每增加一个正方形边长,都需要检查三个方向的dp值,这是否意味着所有三个方向都必须是相同的正方形边长才能形成更大的正方形?
▷