📜  二元矩阵中的最大正方形,多个查询最多有 K 个 1(1)

📅  最后修改于: 2023-12-03 14:49:00.973000             🧑  作者: Mango

二元矩阵中的最大正方形,多个查询最多有 K 个 1

本文将会介绍如何在二元矩阵中查找最大的正方形,并且在多个查询中限制最多只能有 K 个 1。

问题描述

给定一个二元矩阵,找到最大的正方形,其中仅包含值为 1 的元素,并且限制查询的最大值为 K。

解决方案
Brute Force

一个显而易见的解决方案是暴力枚举所有的正方形,然后找到最大值。这个算法的时间复杂度是 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)。