📅  最后修改于: 2023-12-03 14:49:00.973000             🧑  作者: Mango
本文将会介绍如何在二元矩阵中查找最大的正方形,并且在多个查询中限制最多只能有 K 个 1。
给定一个二元矩阵,找到最大的正方形,其中仅包含值为 1 的元素,并且限制查询的最大值为 K。
一个显而易见的解决方案是暴力枚举所有的正方形,然后找到最大值。这个算法的时间复杂度是 O(n^3),其中 n 是矩阵的边长。
我们可以用动态规划来解决这个问题。设 dp(i,j) 表示以 (i,j) 为右下角的最大正方形的宽度。如果 matrix(i,j) = 0,则 dp(i,j) = 0。否则,dp(i,j) 取决于左、上、左上三个元素的值。具体地,我们有:
dp(i,j) = min(dp(i-1,j), dp(i,j-1), dp(i-1,j-1)) + 1
为了避免重复计算,我们可以使用一个辅助数组 preSum(i,j) 来记录矩阵中每一行前缀和。具体来说,preSum(i,j) 表示矩阵第 i 行前 j 列中值为 1 的元素的个数。这使得我们可以在 O(1) 时间内计算出每个子矩阵中值为 1 的元素的个数。
如果我们知道了矩阵中每个正方形中值为 1 的元素的个数,我们就可以二分查找最大的正方形。具体来说,我们可以从大到小枚举正方形的边长,然后判断每个正方形中值为 1 的元素的个数是否小于等于 K。如果是,我们就找到了最大的正方形。
这个算法的时间复杂度是 O(n^2 log n),空间复杂度是 O(n^2)。
class Solution:
def maxSquare(self, matrix: List[List[int]], k: int) -> int:
m, n = len(matrix), len(matrix[0])
preSum = [[0] * (n+1) for _ in range(m)]
for i in range(m):
for j in range(1, n+1):
preSum[i][j] = preSum[i][j-1] + matrix[i][j-1]
# 计算每个正方形中值为 1 的元素的个数
def countOnes(x1, y1, x2, y2):
cnt = 0
for i in range(x1, x2+1):
cnt += preSum[i][y2] - preSum[i][y1-1]
return cnt
# 判断一个正方形是否满足条件
def checkSquare(sz):
for i in range(m-sz+1):
for j in range(n-sz+1):
if countOnes(i, j, i+sz-1, j+sz-1) <= k:
return True
return False
# 二分查找答案
left, right = 0, min(m, n)
ans = 0
while left <= right:
mid = (left + right) // 2
if checkSquare(mid):
ans = mid
left = mid + 1
else:
right = mid - 1
return ans ** 2
本文介绍了一个二元矩阵中查找最大正方形的算法,并且限制了查询结果的最大值。我们用动态规划来计算每个正方形中值为 1 的元素的个数,并用二分查找来找到最大的正方形。这个算法的时间复杂度是 O(n^2 log n),空间复杂度是 O(n^2)。