返回

数据结构与算法:解码 LeetCode 221,解锁最大正方形

前端

在计算机科学的世界里,算法如同一道道耐人寻味的谜题,等待着人们去探索和破解。LeetCode 221 题正是这样一道妙趣横生的难题,它考验着程序员对动态规划的掌握程度,以及对问题本质的深刻理解。本文将带您踏上 LeetCode 221 的解题之旅,从动态规划的视角出发,层层剥开题目的奥秘,并用 JavaScript 语言为您呈现清晰易懂的代码实现。

题目背景

LeetCode 221 题的背景非常简单,它给定一个由 '0''1' 组成的二维矩阵,要求我们找到只包含 '1' 的最大正方形,并返回其面积。例如,对于以下矩阵:

[
  ["1", "0", "1", "0", "0"],
  ["1", "0", "1", "1", "1"],
  ["1", "1", "1", "1", "1"],
  ["1", "0", "0", "1", "0"]
]

最大正方形的边长为 3,因此面积为 9。

解题思路

解决 LeetCode 221 题的关键在于理解动态规划的思想。动态规划是一种解决问题的策略,它将大问题分解成一系列小问题,并逐一求解。在 LeetCode 221 题中,我们可以将矩阵的每个元素视为一个小问题,并利用动态规划的思想逐步求解。

具体来说,我们可以定义一个二维数组 dp,其中 dp[i][j] 表示以 (i, j) 为右下角的子矩阵中,最大正方形的边长。我们从矩阵的左上角开始,逐行逐列地计算 dp 数组。当我们计算到 (i, j) 时,我们可以通过以下公式来计算 dp[i][j]

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

其中:

  • dp[i-1][j] 表示以 (i-1, j) 为右下角的子矩阵中,最大正方形的边长。
  • dp[i][j-1] 表示以 (i, j-1) 为右下角的子矩阵中,最大正方形的边长。
  • dp[i-1][j-1] 表示以 (i-1, j-1) 为右下角的子矩阵中,最大正方形的边长。

如果 matrix[i][j]'0',则 dp[i][j] 为 0,因为以 (i, j) 为右下角的子矩阵中,不可能存在正方形。

代码实现

掌握了动态规划的解题思路后,我们就可以用 JavaScript 语言来实现算法。代码如下:

/**
 * 给定一个由 '0' 和 '1' 组成的二维矩阵,找到只包含 '1' 的最大正方形,并返回其面积。
 *
 * @param {character[][]} matrix 二维矩阵
 * @return {number} 最大正方形的面积
 */
const maximalSquare = function(matrix) {
  if (!matrix || matrix.length === 0 || matrix[0].length === 0) {
    return 0;
  }

  const m = matrix.length;
  const n = matrix[0].length;
  const dp = new Array(m).fill(0).map(() => new Array(n).fill(0));

  let maxSide = 0;
  for (let i = 0; i < m; i++) {
    dp[i][0] = matrix[i][0] === '1' ? 1 : 0;
    maxSide = Math.max(maxSide, dp[i][0]);
  }

  for (let j = 0; j < n; j++) {
    dp[0][j] = matrix[0][j] === '1' ? 1 : 0;
    maxSide = Math.max(maxSide, dp[0][j]);
  }

  for (let i = 1; i < m; i++) {
    for (let j = 1; j < n; j++) {
      if (matrix[i][j] === '1') {
        dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1;
        maxSide = Math.max(maxSide, dp[i][j]);
      }
    }
  }

  return maxSide * maxSide;
};

结语

LeetCode 221 题是一道经典的算法题,它考验着程序员对动态规划的理解和应用能力。通过本文的讲解,您应该已经对 LeetCode 221 题的解题思路和代码实现有了清晰的认识。如果您想要进一步提高自己的算法能力,我建议您多多练习 LeetCode 上的题目,并不断总结和归纳解题经验。我相信,通过坚持不懈的努力,您一定能够成为一名优秀的算法工程师!