一起刷LeetCode——最大矩形(动态规划)

170 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

最大矩形

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

来源:leetcode.cn/problems/ma…

分析

  • 之前在写柱状图中最大矩形的时候,使用的是单调栈,但是最近在写了很多动态规划之后,觉得在矩阵中的最大矩形也可以使用动态规划来实现

动态规划

  • 定义状态:dp[i][j]表示矩阵matrix的第i行第j列的矩形面积
  • 状态初始化:对矩阵按行遍历,dp[0]和matrix的第一行一样
  • 状态转移:
    • 如果dp[i][j]是1,dp[i][j] = dp[i-1]j+1
    • 如果dp[i][j]是0,dp[i][j] = 0
  • 得到有状态的dp数组后,不能直接得到答案,需要对当前行遍历,找到本行的最小值然后乘矩阵cell的个数从而得到最大矩形的面积值

代码

/**
 * @param {character[][]} matrix
 * @return {number}
 */
var maximalRectangle = function(matrix) {
    if (matrix.length <= 0) return 0;
    let n = matrix.length;
    let m = matrix[0].length;
    let dp = new Array(n).fill().map(() => new Array(m).fill(0));
    let maxArea = 0;
    for (let i = 0; i < n; i++) {
      for (let j = 0; j < m; j++) {
        if (i == 0){
            dp[i][j] = matrix[i][j] == '1' ? 1 : 0;
        } else {
            dp[i][j] = matrix[i][j] == '1' ? (dp[i-1][j] + 1) : 0;
        }
        let min = dp[i][j];
        for (let k = j; k >= 0; k--) {
          if (min == 0) break;
          if (dp[i][k] < min) min = dp[i][k];
          maxArea = Math.max(maxArea, min * (j - k + 1));
        }
      }
    }
    return maxArea;
  }
};

总结

  • 动态规划的题目有很多的变化,状态dp有一维数组、二维数组,有些题目dp[x]或者dp[x][y]就是所得答案,也有维护了状态之后,需要对这个状态的数据进一步的分析得到答案,但是核心都是一样的,动态规划的题目中都有“状态”,以及“状态”的转移,至于状态怎么转移,和怎么定义状态有关,如果定义的状态不一样,状态转移方程也会不同,因此在解动态转移题目或者看题解的时候,更多的需要感受在某种定义下的状态是如何转移的,根据不同的情况,写出转移方程,这样主体的代码就可以写出来了。再加一些某些特定题目的特殊情况处理,一般都可以很好的解决问题
  • 动态规划作为常用的解题方法,最近写的比较多,这篇作为动态规划的完结篇,动态规划就暂告一个段落了
  • 今天也是有收获的一天