蓝桥杯刷题016——最大子矩阵(尺取法+单调队列)

news2024/11/26 3:27:05

题目来源:最大子矩阵 - 蓝桥云课 (lanqiao.cn)

问题描述

小明有一个大小为 N×M 的矩阵, 可以理解为一个 N 行 M 列的二维数组。

我们定义一个矩阵 m 的稳定度 f(m) 为f(m)=max(m)−min(m), 其中 max(m) 表示矩阵 m 中的最大值, min(m) 表示矩阵 m 中的最小值。

现在小明想要从这个矩阵中找到一个稳定度不大于 limit 的子矩阵, 同时他还希望这个子矩阵的面积越大越好 (面积可以理解为矩阵中元素个数)。

子矩阵定义如下: 从原矩阵中选择一组连续的行和一组连续的列, 这些行列交点上的元素组成的矩阵即为一个子矩阵。

输入格式

第一行输入两个整数 N,M, 表示矩阵的大小

接下来 N 行, 侮行输入 M 个整数,表示这个矩阵

最后一行输入一个整数 limit, 表示限制

辎出格式

输出一个整数. 分别表示小明选择的子矩阵的最大面积

样例输入

3 4
2 0 7 9
0 6 9 7
8 4 6 4
8

样例输出

6

样例说明

满足稳定度不大于 8 的且面积最大的子矩阵总共有三个, 他们的面积都是 6 (粗体表示子矩阵元素)

2 0 7 9

0 6 9 7

8 4 6 4             

2 0 7 9

0 6 9 7

8 4 6 4

2 0 7 9

6 9 7

4 6 4

评测用例规模与约定

对于所有评测用例, 0≤0≤ 矩阵元素值, limit ≤105≤105 。

题目大意

给定一个N*M的二维矩阵和一个数字limlit,求出符合稳定度f(m)<=limit面积最大的子矩阵
f(m)为当前子矩阵的最大值-最小值

解法一:暴力法(通过30%)

        通过四重循环(四条边)枚举每个子矩阵,然后再计算当前子矩阵的最大值和最小值之差,若差值满足<=limit,则维护更新面积最大值。
算法复杂度大于O(n^4)

解法二: 尺取法+单调队列(通过100%)

解题关键(三问):

1、如何较为快速地确定当前子矩阵的大小?

双指针算法(尺取法)

【图解】尺取法 

1、一开始左右指针都是从左端点开始 

 

 2、右指针先向右移动

 

3、右指针移动到刚好满足f(m)<=limit 的临界位置

 

4、右指针再向右移动,这时候在区间[l, r']就不满足 f(m)<=limit 

 

5、此时开始移动左指针 

 

6、当左指针移动到刚好满足f(m)<=limit 的临界位置时,右指针开始移动,这样周而复始,直到右指针达到终点。

 

 

        观察数据,可发现行的数据范围较小,列的数据范围较大,因此子矩阵的上下边可以通二.重遍历确定,复杂度O(n^2),子矩阵的左右边采用双指针算法进行确定,复杂度O(m)
算法复杂度O(n^2m)

  

2、如何较为快速地找出当前子矩阵的两个最值?

        每次移动左右指针,都会后一整列的数字进入或退出当前子矩阵,我们需要先计算出当前列[up,down]范围的最值优化:通过转置矩阵,我们可以利用切片的方式,不用循环求出原矩阵每一列[up,down]范围内的最值

  

3、当前子矩阵实在不断移动的,如何在移动过程中维护最值?

        使用两个队列分别记录当前子矩阵的最大值和最小值,维护队列的单调性,双指针移动过程中时刻更新队列。

单调队列

维护最大值的单调队列示例:

         第一个数字直接加入队列,后面每一列如果出现的数字比队列最后一个元素小,则加入队列,否则去掉队列最后一个元素, 再与队列最后一个比较,直到队列为空或者该数字比队列最后一个元素小再将该数字加入队列。

 

维护最大值的单调队列,内部元素是递减排列的

维护最小值的单调队列,内部元素是递增排列的

解题思路:双指针+单调队列

1、二重循环对矩阵的上下边界进行遍历
2、对于每个确定的上下边界up,down,左右边界采用双指针算法确定

3、使用两个队列分别记录当前子矩阵的最大值和最小值,维护队列的单调性,双指针移动过程中时刻更新队列
4、初始res=0保存结果,双指针移动过程中维护最大值

代码演示

from collections import deque
n, m = map(int, input().split())
mat = [list(map(int, input().split())) for _ in range(n)]   # 二维列表存矩阵:n行m列
lim = int(input())
max_res = 0

# 转置矩阵    m行n列  
remat = [[0] * n for _ in range(m)]
for i in range(m):                                          
    for j in range(n):
        remat[i][j] = mat[j][i]

for up in range(n):                # 两个for循环遍历上下边
    for down in range(up, n):
        l = 0    # 左指针初始化
        maxq = deque() # 最大值的单调队列
        minq = deque() # 最小值的单调队列
        #maxq.append(max(remat[l][up: down + 1]))    
        #minq.append(min(remat[l][up: down + 1]))
        for r in range(0, m):
            newmax = max(remat[r][up: down + 1])  # 右边新的一列l:[up,down]最大值
            while len(maxq) and maxq[-1] < newmax:# 最大值的单调队列的最后一个比新的最大值小
                maxq.pop()                        # 删除队列最后一个
            maxq.append(newmax)                   # 把新的一列的最大值放入队列
            newmin = min(remat[r][up: down + 1])  
            while len(minq) and minq[-1] > newmin:
                minq.pop()
            minq.append(newmin)
            cumax, cumin = maxq[0], minq[0]       # 子矩阵的最大值和最小值
            while cumax - cumin > lim and l < r:  # 最大-最小>lim,左指针<右指针
                if len(maxq) and max(remat[l][up: down + 1]) == maxq[0]: # 最左边的一列的最大值是子矩阵的最大值
                    maxq.popleft()                                       # 删除最大值,因为左指针要向右移动
                if len(minq) and min(remat[l][up: down + 1]) == minq[0]:
                    minq.popleft()
                cumax, cumin = maxq[0], minq[0]        #  更新子矩阵的最大值和最小值
                l += 1                                 #  左指针要向右移动
            if cumax - cumin > lim:                    # 特判:如果l=r且最大-最小>lim
                continue    
            cu_square = (r - l + 1) * (down - up + 1)  # 计算面积
            max_res = max(max_res, cu_square)
print(max_res)

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/181160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

朴素贝叶斯分类

一、朴素贝叶斯法原理 1.基本原理 朴素贝叶斯法(Naive Bayes)是一种基础分类算法&#xff0c;它的核心是贝叶斯定理条件独立性假设。贝叶斯定理描述的是两个条件概率之间的关系&#xff0c;对两个事件A和B&#xff0c;由乘法法则易知(A∩B)P(A)P(B│A)P(B)P(A│B)(A∩B)P(A)P(…

离散数学与组合数学-06特殊的图

文章目录离散数学与组合数学-06特殊的图6.1 欧拉图6.1.1 哥尼斯堡七桥问题6.1.2 欧拉图的定义6.1.3 无向欧拉图的判定6.1.4 有向欧拉图的判定6.1.5 一笔画问题6.1.6 求回路6.2 哈密顿图6.2.1 周游世界问题6.2.2 哈密顿图的定义6.2.3 哈密顿图的必要条件6.2.4 哈密顿图的充分条件…

Hadoop基础之《(5)—MapReduce概述》

一、什么是MapReduce MapReduce将计算过程分为两个阶段&#xff1a;Map和Reduce。 1、Map阶段并行处理输入数据。 2、Reduce阶段对map结果进行汇总。 二、结构图 三、HDFS、Yarn、MapReduce三者之间的调用关系 HDFS三台服务器&#xff0c;第一台上有DataNode和NameNode。第二…

如何像程序员一样思考

如何像程序员一样思考 全世界越来越多的人发现了软件开发的乐趣和兴奋。一个你构建东西的职业&#xff0c;去打破它们&#xff0c;然后再把它们构建得更好。您可以经常设定自己的工作时间并与来自全球各地的客户一起工作的职业。一个可以自己当老板的职业&#xff1f;编程在 2…

android12.0(S) Launcher3 导入 AndroidStudio 调试编译

验证环境 aosp 12.0 源码&#xff0c;分支 android-12.0.0_r3 可以参考之前写的 android12.0(S) Pixel 3XL (QCOM 845) 编译刷机 AndroidStudio 版本 Android Studio Arctic Fox | 2020.3.1 Patch 4 gradle 版本 gradle-7.0.2-bin.zip gradle:7.0.4 二手 Pixel 3 XL一台可直…

[WUSTCTF2020]颜值成绩查询(布尔注入)

目录 信息收集 脚本 reference 信息收集 输入1出现固定的回显&#xff0c;输入2-4出现乱码 Hi admin, your score is: 100 输入其他特殊字符无回显&#xff0c;也无报错回显 采用布尔注入进行判断 布尔注入原理 代码存在SQL注入漏洞&#xff0c;然而页面即不会回显数据&am…

【C++算法图解专栏】一篇文章带你掌握尺取法(双指针)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为 0 基础刚入门数据结构与算法的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们一起交流~ &#x1f4da;专栏地址&#xff1a;https://blog.csdn.net/Newin…

java spring IOC xml方式工厂Bean操作

spring中有两种Bean 第一种 普通 Bean 就是我们在配置文件中 定义的类对象 创建bean 并定义相关的id和声明类对象 普通bean的特点在于 在配置文件中定义的类型 也就是返回类型 就比如 你定义的是一个 book类的类型 那你这个bean返回的 也比如是个book类型的对象 第二种 是在工…

模拟实现vector/迭代器失效问题

对于STL&#xff0c;我们不仅学会使用STL,还要了解其底层原理&#xff0c;这样一来&#xff0c;我们就能知道什么时候用string好&#xff0c;什么时候用vector&#xff0c;什么时候用list&#xff0c;哪种方法效率高等等。其次了解了STL的底层原理&#xff0c;也助于我们的C功力…

RTF、RIR、Steering Vector傻傻分不清

RTF&#xff1a; Relative transfer function&#xff0c;相对传递函数RIR: Room impulse response&#xff0c;空间冲击响应Steering vector: 导向矢量场景问题定义&#xff1a;空间中存在I个麦克风和J个声源&#xff0c;麦克风采集到的信号其中&#xff0c;麦克i的信号其中表…

一起自学SLAM算法:9.1 ORB-SLAM2算法

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 下面将从原理分析、源码解读和安装与运行这3个方面展开讲解ORB-SLAM2算法。 9.1.1 ORB-SLAM2原理分析 前面已经说过&#xff0c;ORB-SLAM2算法是特征点法的典型代表。因此在下面的分析中&#xff0c;首先介绍一…

被删库勒索了,怎么使用docker进行MySQL容器的管理?

大家觉得写还可以&#xff0c;可以点赞、收藏、关注一下吧&#xff01; 也可以到我的个人博客参观一下&#xff0c;估计近几年都会一直更新&#xff01;和我做个朋友吧&#xff01;https://motongxue.cn 起因&#xff1a;云服务器MySQL密码设置的太简单了&#xff0c;导致到被入…

路由策略实验

1.先配置IP和环回 [Huawei]sysname R1 [R1]interface GigabitEthernet 0/0/0 [R1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 [R1-GigabitEthernet0/0/0]int g 0/0/1 [R1-GigabitEthernet0/0/1]ip add 22.1.1.1 24 [R1-GigabitEthernet0/0/1]q [R1]int l 0 [R1-LoopBack0]ip ad…

ETHDenver 2023 的 Cartesi BUIDLathon 项目创意

希望你在了解Cartesi之前&#xff0c;谨慎对待自己的行为。一旦你开始研究并搜寻可以使用Cartesi Rollups构建的项目或者应用&#xff0c;你就会陷入一个令人兴奋的螺旋洞穴中&#xff0c;你会上瘾。如果你想在2023年中建造一些很具有意义的事情&#xff0c;那你就来对地方了。…

Python01概述 基础语法 判断

Python概述 第二章-Python基础语法 01-字面量 02-注释 03-变量 04-数据类型 05-数据类型转换 06-标识符 07-运算符 08-字符串的三种定义方式 09-字符串的拼接 10-字符串格式化 11-字符串格式化的精度控制 12-字符串格式化的方式-快速写法 13-对表达式进行格式化 14-字符串格…

Java语法核心——面向对象编程

目录 面向过程思想概述 面向对象思想概述 面向对象思想特点及举例 类与对象的关系 类的定义 类与对象的案例(demo02) 对象内存存储机制 成员变量和局部变量的区别 private关键字 面向过程思想概述 我们回想一下&#xff0c;这几天我们完成一个需求的步骤&#xff1a;首…

echarts数据可视化项目搭建(一)

目录直角坐标系通用配置项tooltiptoolboxlegenddataZoom柱状图常见效果折线图常见效果散点图常见效果其他坐标系饼图基本实现常见效果地图地图基本展示不同城市颜色不同地图与散点图结合雷达图仪表盘本博客内容参考黑马课程&#xff0c;详细信息请参考以下网址 Bilibili官方黑…

Apache Superset 开源商业智能大数据可视化

Apache Superset 是一款现代化的开源大数据工具&#xff0c;也是企业级商业智能 Web 应用&#xff0c;用于数据探索分析和数据可视化。 Apache Superset 是一个适合企业日常生产环境中使用的商业智能可视化工具。它具有快速、轻量、直观的特点&#xff0c;任何用户都可以轻松地…

Spring Boot学习之Shiro

文章目录零 全部源码地址一 Shiro简介1.1 Shiro功能1.2 Shiro架构&#xff08;外部视角&#xff09;1.3 Shiro架构&#xff08;内部视角&#xff09;二 Shiro快速入门2.1 演示代码&部分源码解读三 Spring Boot集成Shio3.0 准备操作3.1 整合Shiro3.2 页面拦截实现3.3 登录认…

ESP32设备驱动-HMC5983磁力计驱动

HMC5983磁力计驱动 1、HMC5983介绍 霍尼韦尔 HMC5983 是一款温度补偿型三轴集成电路磁力计。这种表面贴装、多芯片模块专为汽车和个人导航、车辆检测和指向等应用的低场磁场传感而设计。 HMC5983 包括我们最先进的高分辨率 HMC118X 系列磁阻传感器和一个 ASIC,该 ASIC 包含…