首页 > 其他分享 >LeetCode题练习与总结:矩形区域不超过 K 的最大数值和--363

LeetCode题练习与总结:矩形区域不超过 K 的最大数值和--363

时间:2024-11-01 22:49:56浏览次数:3  
标签:边界 -- 复杂度 数值 LeetCode 枚举 矩形 363 TreeSet

一、题目描述

给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。

题目数据保证总会存在一个数值和不超过 k 的矩形区域。

示例 1:

输入:matrix = [[1,0,1],[0,-2,3]], k = 2
输出:2
解释:蓝色边框圈出来的矩形区域 [[0, 1], [-2, 3]] 的数值和是 2,且 2 是不超过 k 的最大数字(k = 2)。

示例 2:

输入:matrix = [[2,2,-1]], k = 3
输出:3

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 100
  • -100 <= matrix[i][j] <= 100
  • -10^5 <= k <= 10^5

二、解题思路

  1. 首先我们需要明确,题目要求我们找到一个矩形区域,使得该区域的数值和不超过k,并且这个数值和尽可能大。

  2. 我们可以使用暴力法来解决这个问题,即枚举所有可能的矩形区域,并计算每个区域的数值和。但是这种方法的时间复杂度是O(m^2 * n^2),在数据规模较大时,效率较低。

  3. 我们可以使用前缀和来优化计算矩形区域数值和的过程。首先计算矩阵的前缀和,然后利用前缀和快速计算任意矩形区域的数值和。

  4. 我们枚举矩形的上下边界,然后利用双指针法枚举矩形的左右边界。在枚举过程中,我们使用一个有序集合(如TreeSet)来维护从上边界到当前行的每一列的数值和。

  5. 对于每个右边界,我们计算从上边界到当前行的每一列的数值和,然后在有序集合中查找是否存在一个数值,使得当前列的数值和减去这个数值的差值不超过k。如果存在,更新答案。

  6. 最终,我们返回答案。

三、具体代码

import java.util.TreeSet;

class Solution {
    public int maxSumSubmatrix(int[][] matrix, int k) {
        int m = matrix.length, n = matrix[0].length;
        int maxSum = Integer.MIN_VALUE;
        
        // 枚举矩形的上边界
        for (int upper = 0; upper < m; upper++) {
            int[] sum = new int[n];
            // 枚举矩形的下边界
            for (int lower = upper; lower < m; lower++) {
                // 计算当前上下边界之间的每一列的数值和
                for (int col = 0; col < n; col++) {
                    sum[col] += matrix[lower][col];
                }
                
                // 使用有序集合维护从上边界到当前行的每一列的数值和
                TreeSet<Integer> sumSet = new TreeSet<>();
                sumSet.add(0);
                int curSum = 0;
                
                // 枚举矩形的右边界
                for (int right = 0; right < n; right++) {
                    curSum += sum[right];
                    // 在有序集合中查找是否存在一个数值,使得当前列的数值和减去这个数值的差值不超过k
                    Integer leftSum = sumSet.ceiling(curSum - k);
                    if (leftSum != null) {
                        maxSum = Math.max(maxSum, curSum - leftSum);
                    }
                    sumSet.add(curSum);
                }
            }
        }
        
        return maxSum;
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 外层循环枚举矩形的上边界,共有 m 种情况。
  • 第二层循环枚举矩形的下边界,共有 m 种情况,但每个下边界都是基于上边界枚举的,所以对于每个上边界,下边界的枚举次数为 m - upper
  • 第三层循环计算当前上下边界之间的每一列的数值和,这一步的时间复杂度为 O(n)
  • 第四层循环枚举矩形的右边界,共有 n 种情况。
  • 在每次枚举右边界时,我们使用 TreeSet 的 ceiling 方法来查找合适的左边界,TreeSet 的 ceiling 方法的时间复杂度为 O(log n),并且我们还要向 TreeSet 中添加当前的前缀和,这个操作的时间复杂度也是 O(log n)

综合以上步骤,总的时间复杂度为:O(m×(m−upper)×n×(O(logn)+O(logn)))

简化后为:O(m^2×n×logn)

2. 空间复杂度
  • sum 数组用于存储当前上下边界之间的每一列的数值和,其空间复杂度为 O(n)
  • sumSet 是一个 TreeSet,它最多会存储 n 个元素,因此其空间复杂度为 O(n)

综合以上空间占用,总的空间复杂度为:O(n+n)

简化后为:O(n)

因此,该算法的时间复杂度为 O(m^2×n×logn),空间复杂度为 O(n)。

五、总结知识点

  • 二维数组操作:代码中使用了二维数组 matrix 来表示输入的矩阵,并通过嵌套循环来遍历矩阵的行和列。

  • 前缀和数组:使用一维数组 sum 来存储当前上下边界之间的每一列的数值和,这是计算矩形区域和的关键优化。

  • 有序集合(TreeSet):使用 TreeSet 来维护一个有序的集合,以便能够快速查找满足条件的数值。

  • TreeSet 方法

    • add(E e):向 TreeSet 中添加一个元素。
    • ceiling(E e):返回 TreeSet 中大于或等于给定元素的最小元素,如果不存在这样的元素,则返回 null
  • 整数类型的最大值:使用 Integer.MIN_VALUE 来初始化 maxSum 变量,确保任何计算出的矩形区域和都能与之比较。

  • 循环与迭代:代码中使用了多层嵌套循环来枚举所有可能的矩形区域的上边界、下边界和右边界。

  • 条件判断:使用 if 语句来判断 TreeSet 中是否存在一个数值,使得当前列的数值和减去这个数值的差值不超过 k

  • 最大值计算:使用 Math.max() 方法来更新最大数值和 maxSum

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

标签:边界,--,复杂度,数值,LeetCode,枚举,矩形,363,TreeSet
From: https://blog.csdn.net/weixin_62860386/article/details/143403554

相关文章

  • LeetCode题练习与总结:水壶问题--365
    一、题目描述有两个水壶,容量分别为 x 和 y 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 target 升。你可以:装满任意一个水壶清空任意一个水壶将水从一个水壶倒入另一个水壶,直到接水壶已满,或倒水壶已空。示例1: 输入:x=3,y=5,target=4输出......
  • 遍历文件夹和子文件夹,删除重复文件
    importosimporthashlibimportshutildeffile_hash(filepath):"""计算文件的MD5哈希值"""hash_md5=hashlib.md5()withopen(filepath,"rb")asf:forchunkiniter(lambda:f.read(4096),b""):......
  • Vue全家桶-Vue-Router详解
    前后端分离阶段URL的hashHTML5的History认识vue-routervue-router的使用路由的默认路径history模式router-link路由懒加载打包效果分析路由的其他属性动态路由基本匹配......
  • [日记] NOIP前集训日记
    模拟赛日期T1T2T3T4TotalRank\(10.29\)\(0/0/100\)\(0/0/0\)\(0/0/0\)\(0/0/0\)\(0/0/100\)\(14/17\)\(10.31\)\(100/100/100\)\(100/100/100\)\(60/50/60\)\(20/20/20\)\(280/270/280\)\(1/?\)\(11.1\)\(50/100......
  • 前后端分离项目上云
    我不知道怎么描述这种心情!当你自己做过的项目,你随时随地都可以访问到,并且还可以作为简历和答辩时随时展示!这种就很爽!!!接下来我就基于阿里云服务器来操作一下前后端项目如何上云!!!我这里使用的是vue+springboot,vue使用的是vite项目,springboot使用的是maven项目。如......
  • 链表和数组的插入删除时间复杂度都是o(n),为什么说链表效率高
    链表和数组的插入删除时间复杂度都是o(n),链表效率高的原因:1.动态内存分配;2.插入和删除操作的局部性;3.避免数组的扩容和复制;4.无需移动大量数据;5.适用于频繁的随机插入和删除;6.简化数据结构维护。链表的节点可以在运行时动态分配内存,而数组在创建时需要分配固定大小的内存。......
  • Websocket整合实现聊天操作
    在实际开发中,尤其是web开发,我该如何做才可以实现消息或者数据的实时更新呢。这里我为大家介绍,websocket长连接,它可以简历连接,且创建一个通道,通道中的数据可以实时更新。废话不多说,接下来我将使用vue+springboot基于websocket来实现一个简单的聊天实现。vue前端代码,这里主要......
  • 【供应链安全】2024年我国软件供应链安全供应市场特点分析及代表性厂商推荐+供应市场
    原创安全牛在供应关系极度敏感的国际形势下,供应链被“武器化”已经成为一个不争的事实。从供应链视角开展软件安全审查,不仅是开展网络安全合规的必然要求,也是保障国家数字经济高质量发展的重要支撑,更是当前国际形势下我国势在必行的重要安全事项。为帮助企业CSO更好地了解当......
  • 高频电子线路---倍频器与振荡器
    目录 倍频电路原理 丙类倍频器原理电路问题:提升滤波方法: 导通角 振荡器 振荡器基本工作原理首先是怎么维持那么如何振荡呢?思考题: 组成要素 振荡器的起振条件平衡条件要点提示 稳定条件 振幅平衡 硬激励起振时: 稳定条件 相位平衡 倍频......
  • Qml-Transition的使用
    Qml-Transition的使用Transition的概述Transition:定义了当状态发生改变时应用的动画属性animations:list:(Transition)过渡的动画属性enabled:bool:状态发生变化时,是否使能此过渡(Transition)动画;属性from:string:过渡的起始状态(State)名称,默认为"*"(任何状态)属性to:......