363. 矩形区域不超过 K 的最大数值和

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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值