[M前缀和] lc1139. 最大的以 1 为边界的正方形(行列前缀和+代码技巧)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M前缀和] lc1139. 最大的以 1 为边界的正方形(行列前缀和+代码技巧)相关的知识,希望对你有一定的参考价值。
文章目录
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. 最佳观光组合(思维+前缀和+算法优化)