title: 2026-01-19-LeetCode刷题笔记-1292-元素和小于等于阈值的正方形的最大边长
date: 2026-01-19
tags:
- 算法学习
- LeetCode
- 二维前缀和
题目信息
- 平台:LeetCode
- 题目:1292. 元素和小于等于阈值的正方形的最大边长
- 难度:Medium
- 题目链接:Maximum Side Length of a Square with Sum Less than or Equal to Threshold
题目描述
给定一个矩阵 mat 和阈值 threshold,找到元素和不超过 threshold 的正方形子矩阵最大边长。
初步思路
- 用二维前缀和快速计算任意子矩阵的元素和。
- 枚举每个位置作为正方形左上角,尝试把当前最大边长继续扩大。
- 记录并更新全局最大边长。
算法分析
- 核心:二维前缀和 + 枚举左上角并逐步扩大边长
- 技巧:前缀和让子矩阵求和变成 O(1)
- 时间复杂度:O(m * n * L),L 为最终最大边长(最坏 O(m * n * min(m, n)))
- 空间复杂度:O(m * n)
前缀和直观解释
A B C
D E F
G H I
想要的子矩形是:
E F
H I
也就是左上角 D 的右下那一块,坐标上是 (1,1) ~ (2,2)。
按拆分思路走一遍
-
大矩形
ABCDEFGHI:对应s[3][3],整张 3x3 的和。 -
减去左边条
ADG:对应s[3][1],剩下的是:B C
E F
H I -
再减去上边条
ABC:对应s[1][3],剩下的是:E F
H I -
A被减了两次,需要补回:对应s[1][1]。
最终公式:
EFHI
= ABCDEFGHI
- ADG
- ABC
+ A
也就是:
s[3][3] - s[3][1] - s[1][3] + s[1][1]
代码实现(Python)
python
"""
ABC
DEF
GHI
"""
"""
要得到
EF
HI
可以先减去左边条ADG,在减去上边条ABC,再加上A(减了两次)
"""
class Solution:
def maxSideLength(self, mat: List[List[int]], threshold: int) -> int:
m,n = len(mat),len(mat[0])
s = [[0]*(n+1) for _ in range(m+1)]
for i,row in enumerate(mat):
for j,x in enumerate(row):
s[i+1][j+1] = s[i+1][j] +s[i][j+1] - s[i][j] + x
#返回左上角在(r1,c1),右下角在(r2,c2)的子矩阵元素和
def query(r1:int,c1:int,r2:int,c2:int)->int:
return s[r2+1][c2+1]-s[r2+1][c1] - s[r1][c2+1]+s[r1][c1]
ans = 0
for i in range(m):
for j in range(n):
#边长为ans+1的正方形,左上角在(i,j),右下角在(i+ans,j+ans)
while i + ans < m and j + ans < n and query(i,j,i+ans,j+ans) <= threshold:
ans += 1
return ans
总结与反思
- 二维前缀和是处理子矩阵和的基础工具。
- 当前实现是"能扩就扩",若需更优可考虑二分边长。