# LeetCode题解:最大正方形面积

# LeetCode题解:最大正方形面积_第1张图片

## 题目描述

在一个由 `'0'` 和 `'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,面积为4。

 

---

 

## 解题思路

### 动态规划法

**核心思想**:  

使用动态规划(Dynamic Programming)记录每个位置作为右下角时能构成的最大正方形的边长。  

- 定义 `dp[i][j]` 表示以 `(i, j)` 为右下角的最大正方形的边长。  

- 若 `matrix[i][j]` 为 `'0'`,则 `dp[i][j] = 0`(无法构成正方形)。  

- 若 `matrix[i][j]` 为 `'1'`,则状态转移方程为:  

  \[

  dp[i][j] = \min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1

  \]  

  该方程的含义是:当前位置的边长由其上方、左方和左上方的三个位置的最小值决定,因为这三个方向共同限制了当前正方形的扩展能力。

 

**边界条件**:  

- 当 `i == 0` 或 `j == 0`(即第一行或第一列)时,若 `matrix[i][j]` 为 `'1'`,则 `dp[i][j] = 1`。

 

**遍历过程**:  

1. 初始化二维数组 `dp`,大小与原矩阵相同。  

2. 遍历矩阵中的每个元素,根据上述规则填充 `dp` 数组。  

3. 在遍历过程中,记录最大边长 `maxSquareSize`。  

4. 最终返回 `maxSquareSize * maxSquareSize`(面积)。

 

---

 

## 代码实现

```java

public class MaximumSquare {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int m = sc.nextInt(); // 行数

        int n = sc.nextInt(); // 列数

        sc.nextLine(); // 清除换行符

        char[][] matrix = new char[m][n];

        for (int i = 0; i < m; i++) {

            String line = sc.nextLine();

            for (int j = 0; j < n; j++) {

                matrix[i][j] = line.charAt(j);

            }

        }

        int maxSquareSize = maximalSquare(matrix);

        System.out.println(maxSquareSize);

    }

 

    public static int maximalSquare(char[][] matrix) {

        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {

            return 0;

        }

        int rows = matrix.length;

        int cols = matrix[0].length;

        int[][] dp = new int[rows][cols];

        int maxSquareSize = 0;

 

        for (int i = 0; i < rows; i++) {

            for (int j = 0; j < cols; 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;

                    }

                    maxSquareSize = Math.max(maxSquareSize, dp[i][j]);

                }

            }

        }

        return maxSquareSize * maxSquareSize;

    }

}

```

 

---

 

## 复杂度分析

- **时间复杂度**:O(mn),其中 m 和 n 分别为矩阵的行数和列数。  

- **空间复杂度**:O(mn),需要额外的二维数组 `dp` 存储中间状态。

 

---

 

## 其他测试用例

### 测试用例1

**输入**:

```

1 5

11111

```

**输出**:1  

**解释**:虽然所有元素都是 `'1'`,但最大正方形的边长为1(仅单个元素)。

 

### 测试用例2

**输入**:

```

3 3

111

111

111

```

**输出**:9  

**解释**:整个矩阵构成一个3x3的正方形,面积为9。

 

---

 

## 总结

通过动态规划方法,能够高效地找到最大正方形的边长。其核心在于利用已计算的子问题结果(以某个位置为右下角的正方形边长),通过状态转移方程推导出更大问题的解。该方法避免了暴力枚举所有可能的正方形,显著降低了时间复杂度。

你可能感兴趣的:(java,动态规划,算法,leetcode,矩阵)