leetcode
leetcode 201 ~ 250
最大正方形

最大正方形

难度:

标签:

题目描述

在一个由 '0''1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。

 

示例 1:

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:4

示例 2:

输入:matrix = [["0","1"],["1","0"]]
输出:1

示例 3:

输入:matrix = [["0"]]
输出:0

 

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 300
  • matrix[i][j]'0''1'

代码结果

运行时间: 99 ms, 内存: 30.3 MB


/*
 * 思路:
 * 我们使用动态规划来解决这个问题。定义一个二维dp数组,其中dp[i][j]表示以(i, j)为右下角的正方形的最大边长。
 * 初始化时,矩阵的第一行和第一列的dp值等于矩阵的值。对于其他元素,如果矩阵值为'1',
 * 则dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1,否则dp[i][j] = 0。
 * 最后,遍历dp数组,找到最大的边长,并计算面积。
 * 此处使用Java Stream API来简化代码。
 */
import java.util.Arrays;
 
public class SolutionStream {
    public int maximalSquare(char[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return 0;
        }
        int rows = matrix.length, cols = matrix[0].length;
        int[] dp = new int[cols + 1];
        int maxSide = 0, prev = 0;
        for (int i = 1; i <= rows; i++) {
            for (int j = 1; j <= cols; j++) {
                int temp = dp[j];
                if (matrix[i - 1][j - 1] == '1') {
                    dp[j] = Math.min(Math.min(dp[j - 1], dp[j]), prev) + 1;
                    maxSide = Math.max(maxSide, dp[j]);
                } else {
                    dp[j] = 0;
                }
                prev = temp;
            }
        }
        return maxSide * maxSide;
    }
}

解释

方法:

这道题使用动态规划来解决。定义二维dp数组,其中dp[i][j]表示以(i,j)为右下角的正方形的最大边长。状态转移方程为:当前位置如果为'1',则dp[i][j] = min(左上角dp值, 正上方dp值, 正左方dp值) + 1。最后返回dp数组中的最大值的平方即为最大正方形面积。

时间复杂度:

O(mn)

空间复杂度:

O(mn)

代码细节讲解

🦆
为什么状态转移方程中要取min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1,这里的min函数具体起到什么作用?
在动态规划中,取min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1的目的是确保在(i, j)位置能形成一个正方形。dp[i][j]的最大值取决于它的上方、左方和左上方三个相邻位置的dp值。只有当这三个位置都能至少构成一个边长为k的正方形时,(i, j)位置才可能构成一个边长为k+1的正方形。因此,取这三个值的最小值确保了不会超出任何一个方向能提供的正方形边长,这是形成一个更大正方形的必要条件。
🦆
在题解中提到初始化第0行和第0列,如果整个矩阵的第一行或第一列全为'0',这种初始化方式是否还适用?
初始化第0行和第0列的方法仍然适用,因为在初始化时,我们根据矩阵中相应位置的值('1'或'0')来设置dp数组的值。如果第一行或第一列的值为'0',对应的dp值将被初始化为0,反映了在这些位置无法形成任何正方形。这种初始化方式确保了dp数组正确地表示了每个位置的最大正方形边长。
🦆
题解中未提及对于空矩阵输入的处理,如何修改代码以确保对于空矩阵的输入不会出现错误?
为了确保空矩阵输入不会导致错误,可以在动态规划算法开始之前加入一个检查,确保矩阵不为空。具体来说,可以在计算m和n(矩阵的行和列数)之后,立即检查它们是否为0。如果m或n为0,函数直接返回0,表示没有任何正方形可以形成。这个检查可以有效防止后续代码在访问空矩阵时出错。
🦆
题解中使用了一个双层循环遍历整个矩阵,这种方法是否会处理所有边界情况,例如矩阵中全是'1'或全是'0'的情况?
双层循环遍历整个矩阵的方法能够处理包括矩阵全为'1'或全为'0'的所有边界情况。当矩阵全为'1'时,dp数组将正确计算出每个位置的最大正方形边长,最终返回整个矩阵能形成的最大正方形面积。当矩阵全为'0'时,dp数组中的所有值将保持为0,函数最终返回0。因此,这种遍历方法确保了算法能在所有可能的矩阵情况下正确运行。

相关问题

最大矩形

给定一个仅包含 01 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

 

示例 1:

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。

示例 2:

输入:matrix = [["0"]]
输出:0

示例 3:

输入:matrix = [["1"]]
输出:1

 

提示:

  • rows == matrix.length
  • cols == matrix[0].length
  • 1 <= row, cols <= 200
  • matrix[i][j]'0''1'

最大加号标志

在一个 n x n 的矩阵 grid 中,除了在数组 mines 中给出的元素为 0,其他每个元素都为 1mines[i] = [xi, yi]表示 grid[xi][yi] == 0

返回  grid 中包含 1 的最大的 轴对齐 加号标志的阶数 。如果未找到加号标志,则返回 0

一个 k 阶由 1 组成的 “轴对称”加号标志 具有中心网格 grid[r][c] == 1 ,以及4个从中心向上、向下、向左、向右延伸,长度为 k-1,由 1 组成的臂。注意,只有加号标志的所有网格要求为 1 ,别的网格可能为 0 也可能为 1

 

示例 1:

输入: n = 5, mines = [[4, 2]]
输出: 2
解释: 在上面的网格中,最大加号标志的阶只能是2。一个标志已在图中标出。

示例 2:

输入: n = 1, mines = [[0, 0]]
输出: 0
解释: 没有加号标志,返回 0 。

 

提示:

  • 1 <= n <= 500
  • 1 <= mines.length <= 5000
  • 0 <= xi, yi < n
  • 每一对 (xi, yi) 都 不重复​​​​​​​