[M前缀和] lc1139. 最大的以 1 为边界的正方形(行列前缀和+代码技巧)

Posted Ypuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M前缀和] lc1139. 最大的以 1 为边界的正方形(行列前缀和+代码技巧)相关的知识,希望对你有一定的参考价值。

文章目录

1. 题目来源

链接:1139. 最大的以 1 为边界的正方形

2. 题目解析

1744 分的题目,实际上采用行、列前缀和,加上一个小性质就能快速解决了。官解写的太长了。

如果 [l, r] 均为 1 的话,则前缀和 s[r] - s[l - 1] = r - l + 1 前缀和值等于区间长度值。

若是正方形,则枚举左上角横坐标 (x, y) 点,再枚举长度 k,那么四个点的位置都可以知道了,再根据前缀和数组快速判断是否为全 1 的区间即可。


注意不要采用二维前缀和,这里需要的是,单行、单列上的前缀和。二维前缀和求的是子矩阵的元素和,意义不一样。

注意代码实现,如何初始化行、列前缀和。如何一次遍历求出行、列前缀和。

注意枚举顺序,要求最大长度,及从最大长度开始递减枚举,若满足要求,便可提前返回。

注意前缀和相减时的坐标关系。


  • 时间复杂度 O ( n m ) O(nm) O(nm)
  • 空间复杂度 O ( n m ) O(nm) O(nm)

class Solution 
public:
    int largest1BorderedSquare(vector<vector<int>>& grid) 
        int n = grid.size(), m = grid[0].size();
        vector<vector<int>> rs(n, vector<int>(m + 1)), cs(m, vector<int>(n + 1));

        // 巧妙的矩阵转置,一次性求出 行、列 的前缀和。注意数组声明的长度        
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ ) 
                rs[i][j + 1] = rs[i][j] + grid[i][j];   // 行前缀和
                cs[j][i + 1] = cs[j][i] + grid[i][j];   // 列前缀和 
            

        // 边界很难处理
        // 优先枚举长度,可以提前 return
        int res = 0;
        for (int d = min(n, m); d; d -- ) 
            for (int i = 0; i + d <= n; i ++ )
                for (int j = 0; j + d <= m; j ++ )
                    if (rs[i][j + d] - rs[i][j] == d &&     // 上。没有减1,这样长度才是 d
                        cs[j][i + d] - cs[j][i] == d &&     // 左
                        rs[i + d - 1][j + d] - rs[i + d - 1][j] == d && // 下。需要减 1
                        cs[j + d - 1][i + d] - cs[j + d - 1][i] == d)   // 右
                        
                        return d * d;
        

        return 0;
    
;

以上是关于[M前缀和] lc1139. 最大的以 1 为边界的正方形(行列前缀和+代码技巧)的主要内容,如果未能解决你的问题,请参考以下文章

[LeetCode] 1139. Largest 1-Bordered Square 最大的以1为边界的正方形

[M前缀和] lc1894. 找到需要补充粉笔的学生编号(二分+模拟+坑点)

[M前缀和] lc1894. 找到需要补充粉笔的学生编号(二分+模拟+坑点)

[M前缀和] lc1014. 最佳观光组合(思维+前缀和+算法优化)

数据结构与算法之深入解析“最大的以1为边界的正方形”的求解思路与算法示例

[Hdp] lc面试题 17.24. 最大子矩阵(前缀和+列压缩+最大子阵和+面试常考)