迪子依旧这么低。。。

科技   2024-10-25 10:10   上海  

精品推荐

《征服数据结构》专栏:50多种数据结构彻底征服

《经典图论算法》专栏:50多种经典图论算法全部掌握


一非C9的硕士毕业生收到比亚迪的offer,薪资待遇:13k*1.36*12,感觉有点低。我查了下比亚迪历年的校招薪资,这个待遇在比亚迪其实不算低,如果是和互联网大厂比确实有点少,但比亚迪毕竟不是互联网行业,核心技术还是以机械和电气为主。






--------------下面是今天的算法题--------------


来看下今天的算法题,这题是LeetCode的第221题:最大正方形。


问题描述



来源:LeetCode第221题
难度:中等

在一个由 '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


  • m == matrix.length

  • n == matrix[i].length

  • 1 <= m, n <= 300

  • matrix[i][j] 为 '0' 或 '1'


问题分析



这题让计算最大正方形面积,只需要找到最大正方形的边长就可以计算面积了。

可以使用动态规划解决,定义二维数组dp[m][n],其中dp[i][j]表示在矩阵中以坐标[i,j]为右下角的最大正方形边长。如果想求dp[i][j],需要判断矩阵中matrix[i][j]的值。

1,如果matrix[i][j]是0就没法构成正方形,所以dp[i][j]=0。
2,如果matrix[i][j]是1,说明可以构成一个正方形,并且这个正方形的边长最小是1。
        2.1,如果求最大值,还需要判断他左上角的值dp[i-1][j-1],如果dp[i-1][j-1]是0,那么以坐标[i,j]为右下角的最大正方形边长就是1,如下图所示

        2.2,如果左上角的值dp[i-1][j-1]不是0,那么以坐标[i,j]为右下角有可能可以构成一个更大的正方形。为啥说是有可能,因为如果要确定他能不能构成一个更大的正方形,还要往它的上边和左边找,看下下面的图。

有可能是下面这种情况,就是左边或者上边的某一个高度小于dp[i-1][j-1]的值,要想构成最大的正方形我们只能取最小的。
也有可能是下面这种,就是左边和上边的高度都不小于dp[i-1][j-1]的值。

所以我们可以得出结论,如果matrix[i,j]是1,那么以它为右下角的最大正方形边长是min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1;


所以我们可以找出递推公式

如果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;


JAVA:
public int maximalSquare(char[][] matrix) {
    // 二维矩阵的宽和高
    int m = matrix.length;
    int n = matrix[0].length;
    int[][] dp = new int[m + 1][n + 1];
    int maxSide = 0;// 最大正方形的宽
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (matrix[i - 1][j - 1] == '1') {
                // 递推公式
                dp[i][j] = Math.min(dp[i - 1][j],
                        Math.min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
                // 记录最大的边长
                maxSide = Math.max(maxSide, dp[i][j]);
            }
        }
    }
    return maxSide * maxSide; // 返回正方形的面积
}

C++:
public:
    int maximalSquare(vector<vector<char>> &matrix) {
        // 二维矩阵的宽和高
        int m = matrix.size();
        int n = matrix[0].size();
        vector<vector<int>> dp(m + 1vector(n + 10));
        int maxSide = 0;// 最大正方形的宽
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (matrix[i - 1][j - 1] == '1') {
                    // 递推公式
                    dp[i][j] = min(dp[i - 1][j],
                                   min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
                    // 记录最大的边长
                    maxSide = max(maxSide, dp[i][j]);
                }
            }
        }
        return maxSide * maxSide; // 返回正方形的面积
    }

Python:
def maximalSquare(self, matrix: List[List[str]]) -> int:
    # 二维矩阵的宽和高
    m, n = len(matrix), len(matrix[0])
    dp = [[0] * (n + 1for _ in range(m + 1)]
    maxSide = 0  # 最大正方形的宽
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if matrix[i - 1][j - 1] == '1':
                # 递推公式
                dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - 1], dp[i][j - 1]) + 1
                # 记录最大的边长
                maxSide = max(maxSide, dp[i][j])
    return maxSide * maxSide  # 返回正方形的面积


笔者简介
博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解800多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以下载我整理的1000多页的PDF算法文档


《征服数据结构》专栏

数组稀疏表(Sparse Table)单向链表双向链表块状链表跳表队列和循环队列双端队列单调队列单调栈双端栈散列表字典树(Trie树)ArrayMapSparseArray二叉树二叉搜索树(BST)笛卡尔树AVL树树堆(Treap)FHQ-Treap哈夫曼树滚动数组差分数组LRU缓存LFU缓存

……


《经典图论算法》专栏

图的介绍图的表示方式邻接矩阵转换广度优先搜索(BFS)深度优先搜索(DFS)A*搜索算法迭代深化深度优先搜索(IDDFS)IDA*算法双向广度优先搜索迪杰斯特拉算法(Dijkstra)贝尔曼-福特算法(Bellman-Ford)SPFA算法弗洛伊德算法(Floyd)卡恩(Kahn)算法基于DFS的拓扑排序约翰逊算法(Johnson)

……

数据结构和算法
王一博,《算法秘籍》作者,1000多页的pdf算法题我也已经整理完成,在公众号“数据结构和算法”中回复关键字“pdf”即可下载。
 最新文章