363. 矩形区域不超过 K 的最大数值和
原始题目链接:https://leetcode.cn/problems/max-sum-of-rectangle-no-larger-than-k/
给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。
题目数据保证总会存在一个数值和不超过 k 的矩形区域。
解题思路:
计算二维矩阵的前缀和,先计算每行的前缀和,再固定列,具体是设置列的两个端点,一左一右,左侧端点从头遍历,右侧端点也从头遍历,即两层for循环,然后最内层循环是行,这样就形成了一个矩阵区域的和,查找的时候利用前缀和的递增特性,使用二分查找方法加快查找速度,查找的点利用数学转换的方法,查找符合条件的下标索引。
代码实现:
class Solution:
def maxSumSubmatrix(self, matrix: List[List[int]], K: int) -> int:
from sortedcontainers import SortedList
# 计算矩阵的行数和列数
row, col = len(matrix), len(matrix[0])
# 计算每一行的前缀和
# 不申请额外空间的话,原地修改原矩阵
for i in range(row):
for j in range(1, col):
matrix[i][j] += matrix[i][j - 1]
ans = float("-inf")
# 固定列的左右两个端点,从左到右,i表示列的左端点,j表是列的右端点
# 最内的循环是遍历行,再用一个变量进行累加,计算矩阵和
# 再将矩阵和的结果存放到一个列表中,再进行查找操作
for i in range(col):
for j in range(i, col):
# 存放矩阵和的结果
pre_sum = SortedList([0])
pre = 0
# 遍历行,开始计算矩阵和
for k in range(row):
# 因为已经计算了每一行的前缀和
# 所以matrix[k][j] - matrix[k][i - 1]就是每一行[i, j]的区域和
pre += matrix[k][j] - (0 if i == 0 else matrix[k][i - 1])
# 找存在一个数值和不超过k,就是pre_cur - k <= 0
# pre_sum(i,j) = pre_sum(0,j) - pre_sum(0,i-1) - k <= 0
# 即:pre_sum(0,j) - k <= pre_sum(0,i-1)
# 那就是在pre_sum找到一个索引位置,这个位置不超过i-1
# 如果存在这个条件下的索引的值,那么找到最大的就是题目要求的结果
# pre_sum存储的是前缀和,即递增的,所以可以使用二分查找来优化算法
idx = pre_sum.bisect_left(pre - K)
# 如果i == len(pre_sum) 表示无解
# 如果在pre_sum数组中,就更新最大值
if idx < len(pre_sum):
ans = max(ans, pre - pre_sum[idx])
pre_sum.add(pre)
return ans
参考文献:
https://leetcode.cn/problems/max-sum-of-rectangle-no-larger-than-k/solution/li-kou-jia-jia-ru-he-qiu-er-wei-shu-zu-d-rjpy/