leetcode-167周赛-1292-元素和小于等于阈值的正方形的最大边长
题目描述;
自己的提交:超时
class Solution: def maxSideLength(self, mat: List[List[int]], threshold: int) -> int: m,n = len(mat),len(mat[0]) res = 0 for i in range(m): for j in range(n): i_,j_ = i+res,j+res while i_ < m and j_ < n: pre = sum(sum(mat[x][j:j_])for x in range(i,i_)) cur = pre + sum(mat[x][j_] for x in range(i,i_+1)) + sum(mat[i_][y] for y in range(j,j_+1)) - mat[i_][j_] if cur <= threshold: res = max(res,j_-j+1) else: break pre = cur i_ += 1 j_ += 1 return res
方法一:前缀和+二分 O(mn*logmin(m,n))
class Solution: def maxSideLength(self, mat: List[List[int]], threshold: int) -> int: m, n = len(mat), len(mat[0]) P = [[0] * (n + 1) for _ in range(m + 1)] for i in range(1, m + 1): for j in range(1, n + 1): P[i][j] = P[i - 1][j] + P[i][j - 1] - P[i - 1][j - 1] + mat[i - 1][j - 1] def getRect(x1, y1, x2, y2): return P[x2][y2] - P[x1 - 1][y2] - P[x2][y1 - 1] + P[x1 - 1][y1 - 1] l, r, ans = 1, min(m, n), 0 while l <= r: mid = (l + r) // 2 find = any(getRect(i, j, i + mid - 1, j + mid - 1) <= threshold for i in range(1, m - mid + 2) for j in range(1, n - mid + 2)) if find: ans = mid l = mid + 1 else: r = mid - 1 return ans
方法二:O(mn)
class Solution: def maxSideLength(self, mat: List[List[int]], threshold: int) -> int: m, n = len(mat), len(mat[0]) P = [[0] * (n + 1) for _ in range(m + 1)] for i in range(1, m + 1): for j in range(1, n + 1): P[i][j] = P[i - 1][j] + P[i][j - 1] - P[i - 1][j - 1] + mat[i - 1][j - 1] def getRect(x1, y1, x2, y2): return P[x2][y2] - P[x1 - 1][y2] - P[x2][y1 - 1] + P[x1 - 1][y1 - 1] r, ans = min(m, n), 0 for i in range(1, m + 1): for j in range(1, n + 1): for c in range(ans + 1, r + 1): if i + c - 1 <= m and j + c - 1 <= n and getRect(i, j, i + c - 1, j + c - 1) <= threshold: ans += 1 else: break return ans