算法第十二天-矩形区域不超过K的最大数值和

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

题目要求


解题思路

来自[宫水三叶]
从题面来看显然是一道[二维前缀和]的题目。本题预处理前缀和的复杂度为O(m* n)
搜索所有子矩阵需要枚举[矩形左上角]和[矩形右下角],复杂度是 O ( m 2 ∗ n 2 ) O(m^2 * n^2) O(m2n2),因此,如果把本题当作二维前缀和模板题来做的话,整体复杂度为 O ( m 2 ∗ n 2 ) O(m^2 * n^2) O(m2n2).
数据范围是 1 0 2 10^2 102,对应的计算量是 1 0 8 10^8 108,理论上会超时,但当我们枚举[矩形左上角](i,j)的时候,我们只需要搜索位于(i,j)的右下方的点(p,q)作为[矩形右下角],所以其实我们是取不满 m 2 ∗ n 2 m^2 * n^2 m2n2的,但是,仍然存在超时风险。

前缀和 & 二分(抽象一维)

我们来细想一下[朴素二维前缀和]解法是如何搜索答案(子矩阵):通过枚举[左上角] & [右下角]来确定某个矩阵
换句话说是通过枚举(i,j)和(p,q)来唯一确定子矩阵的四条边,每个坐标点可以看作确定子矩阵的某条边。
既然要确定的边有四条,我们如何降低复杂呢?
简单的,我们先思考一下同样是枚举的[两数之和]问题
在[两数之和]中可以暴力枚举两个数,也可以只枚举其中一个数,然后使用数据结构(哈希表)来加速找另一个数(这是一个通用的[降低枚举复杂度]思考方向)。
对应到本题,我们可以枚举其中三条边,然后使用数据结构来加速找第四条边。
当我们确定了三条边(红色)之后,形成的子矩阵就单纯取决于第四条边的位置(黄色):
在这里插入图片描述

于是问题转换为[如何快速求得第四条边(黄色)的位置在哪]。
我们可以进一步将问题缩小,考虑矩阵之有一行(一维)的情况:

这时候问题进一步转换为[在一维数组中,求解和不超过K的最大连续子数组之和]。
对于这个一维问题,我们可以先预处理出[前缀和],然后枚举子数组的左端点,然后通过[二分]来求解其右端点的位置。
假定我们已经求得一维数组的前缀和数组sum,即可得下标范围[i,j]的和为:
areaSum(i,j) = sum[j] - sum[i-1] <=k
经过变形后得:
sum[j] <= k + sum[i-1]
我们两种思路来最大化areaSum(i,j):

  • 确定(枚举)左端点位置i,求得符合条件的最大右端点sum[j]
  • 确定(枚举)右端点位置j,求得符合条件的最小左端点sum[i]
    对于没有负权值的一维数组,我们可以枚举左端点i,同时利用前缀和的[单调递增]特性,通过[二分]找到符合sum[j] <= k +sum[i-1]条件的最大值sum[j],从而求解出答案
    但是如果是含有负权值的话,前缀和将会丢失[单调递增]的特性,我们也就无法使用枚举i并结合[二分]查找j的做法。
    这时候需要将过程反过来处理:我们从左到右枚举j,并使用[有序集合]结构维护遍历过的位置,找到符合sun[j] - k <= sum[i] 条件最小值sum[i],从而求解出答案。
    基于上述分析,解决这样的一维数组问题复杂度是 O ( n l o g n ) O(n log n) O(nlogn)。将这样子思路应用到二维需要一点点抽象能力。
    同时,将一维思路引用到本题(二维),复杂度要么是 O ( m 2 ∗ n l o g n ) O(m ^2 * n logn) O(m2nlogn)要么是 O ( n 2 ∗ m l o g m ) O(n^2 * m log m) O(n2mlogm)
    我们先不考虑[最大化二分收益]问题,先假设我们是固定枚举[上下行]和[右边列],这时候唯一能够确定一个子矩阵则是取决于[左边列]:

重点是如何与[一维]问题进行关联:显然[目标子矩阵的和]等于[子矩阵的右边列 与 原矩阵的左边列 形成的子矩阵和] - [子矩阵左边列 与 原矩阵左边列 形成的子矩阵和]

我们可以使用area[r]代表[子矩阵的右边列 与 原矩阵的左边列 形成的子矩阵之和],使用area[l-1]代表[子矩阵的左边列 与 原矩阵的左边列 形成的子矩阵和]的话,则有:
target = area[r] - area[l-1] <=k
这与我们[一维问题]完全一直,同时由[上下行]&[右边列]可与直接确定area[r]的大小,通过[有序集合]存储我们遍历r过程中固定所有area[r]从而实现[二分]查找符合area[r] - k <= area[l-1]条件的最小area[l-1]
至此,我们通过预处理前缀和+容斥原理彻底将题目转换为[一维问题]进行来求解。

其他解法

首先有三个变量row,col,res第一个记录行,第二个记录列,第三个记录矩形和
然后看二维矩阵matrix,我们有两个索引left,right,这两个索引代表列与列之间的范围。
开始先从第0列开始,同时也作为左边的列left,然后再取右边的列right逐渐将右移。并且记录同一行左边的列与右边的列的和.
这里有个需要注意的,我们首先是取第0列作为左边的列,然后右边的列依次从第0列开始逐渐到最后一列,在此期间同一行的左右列会逐渐相加。当我们这次一整个循环完,左边的列会更新成1,也就是for left in range(col),然后重置新一轮的计算和,再继续循环右边的列。
接下来当我们累加和计算完之后就相当于将二维变成了一维,之后我们将在这个一维里面计算最大的矩形和。一个列表lst用来存放累加的和,一个变量cur用来累加之前算出来的累加列表sums。
我们这里需要找到的是最大的矩形和,但是有一个条件,那就是不大于k。比如我们要求sums(i,j)=sums(0,j)-sums(0,i-1)那么我们可以把sums(i,j)=k且不大于k,sums(0,j)-sums(0,i-1)<=k,可以写成sums(0,j)-k<=sums(0,i-1),我们可以看这个式子是否成立。
所以当我们累加和第一个值之后loc = bisect.bisect_left(lst,cur-k)可以看成sums(0,j)-k<=sums(0,i-1),接下来进行一个if判断,如果成立那么cur-lst[loc]可以看成sums(0,j)-sums(0,i-1)<=k计算出值,之后进行res最大值计算。

想不起来可以参看

https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/solution/javacong-bao-li-kai-shi-you-hua-pei-tu-pei-zhu-shi/

代码

class Solution:def maxSumSubmatrix(self, matrix: List[List[int]], k: int) -> int:import bisectrow = len(matrix)col = len(matrix[0])res = float("-inf")for left in range(col):# 以left为左边界,每行的总和_sum = [0] * rowfor right in range(left, col):for j in range(row):_sum[j] += matrix[j][right]# 在left,right为边界下的矩阵,求不超过K的最大数值和arr = [0]cur = 0for tmp in _sum:cur += tmp# 二分法loc = bisect.bisect_left(arr, cur - k)if loc < len(arr):res = max(cur - arr[loc], res)# 把累加和加入bisect.insort(arr, cur)return res

复杂度分析

时间复杂度: O ( m 2 ∗ n 2 ) O(m^2 * n^2 ) O(m2n2)
空间复杂度: O ( n ) O(n) O(n)

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

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

相关文章

【数据库原理】(5)关系数据库的关系数据结构

关系及相关概念 在关系模型中,无论是实体还是实体之间的联系均由关系(二维表)来表示。 1.域&#xff08;Domain&#xff09; 定义&#xff1a;域是一组具有相同数据类型的值的集合。例子&#xff1a;实数集合、整数集合、英文字母集合等。 2.笛卡儿积&#xff08;Cartesian…

Spring之事务

当我们在某个方法上加了Transactional注解后&#xff0c;就表示该方法在调用时会开启Spring事务&#xff0c;而这个方法所在的类所对应的Bean对象会是该类的代理对象。 Spring事务的代理对象执行某个方法时的步骤&#xff1a; 1. 判断当前执行的方法是否存在Transactional注解…

mysql进阶-不同的count()性能

目录 一.count() 的含义 二.性能比较 三.结论 统计数据的四种count()方式包括&#xff1a;count(1) 、count(*)、count(id)、count(字段)。 假设数据库的存储引擎是InnoDB,如果是MyISAM,则表的总行数是已经存储的(没有where条件的情况下)&#xff0c;可以直接返回。 一.cou…

YOLOv5改进 | 卷积篇 | SAConv轻量化的可切换空洞卷积(附修改后的C3+Bottleneck)

一、本文介绍 本文给大家带来的改进机制是可切换的空洞卷积(Switchable Atrous Convolution, SAC)是一种创新的卷积网络机制,专为增强物体检测和分割任务中的特征提取而设计。SAC的核心思想是在相同的输入特征上应用不同的空洞率进行卷积,并通过特别设计的开关函数来融合这…

2023-应用开发中遇到的问题与解决方案

随着科技的不断发展&#xff0c;应用开发已经成为了当今社会中不可或缺的一部分。无论是手机应用、网页应用还是桌面应用&#xff0c;它们都为我们的生活带来了极大的便利。然而&#xff0c;在应用开发的过程中&#xff0c;我们往往会遇到各种各样的问题。作者将针对应用开发过…

2024.1.5 Hadoop各组件工作原理,面试题

目录 1 . 简述下分布式和集群的区别 2. Hadoop的三大组件是什么? 3. 请简述hive元数据服务配置的三种模式? 4. 数据库与数据仓库的区别? 5. 简述下数据仓库经典三层架构? 6. 请简述内部表和外部表的区别? 7. 简述Hive的特点,以及Hive 和RDBMS有什么异同 8. hive中无…

平铺式桌面环境体验之I3WM

平铺式桌面环境体验之I3WM 一说到Linux桌面&#xff0c;大家常用的桌面环境可能是 GNOME、KDE或者Xfce&#xff08;窗口可层叠&#xff09;&#xff0c;因为这几个流行的桌面环境更容易上手&#xff0c;更适合从Windows向Linux过渡。 但今天&#xff0c;我们来体验一种平铺式…

【SpringBoot】分组校验和自定义校验(注解)

分组检验 参数校验时&#xff0c;我们希望不同的方法参数校验规则不同&#xff0c;这时就需要分组校验。 public class Category {NotNull(groups Update.class)private Integer id;//主键IDNotEmptyprivate String categoryName;//分类名称// NotEmpty(groups {Add.class,…

java基础之Java8新特性-Stream(流)

简介 流&#xff08;Stream&#xff09;是 Java 8 引入的一种处理集合数据的抽象概念&#xff0c;它提供了一种更简洁、更灵活的方式来操作和处理集合数据。流可以看作是一系列元素的管道&#xff0c;可以对这些元素进行筛选、转换、排序、归约等操作&#xff0c;实现各种数据…

剑指offer题解合集——Week3day3

文章目录 剑指offerWeek3周三&#xff1a;树的子结构AC代码思路&#xff1a; 剑指offerWeek3 周三&#xff1a;树的子结构 题目链接&#xff1a;树的子结构 输入两棵二叉树 A&#xff0c;B&#xff0c;判断 B 是不是 A的子结构。我们规定空树不是任何树的子结构。数据范围 每…

【人工智能】深入了解人工智能的核心算法与应用实践

人工智能 学习AI要看的第一本书人工智能应当以人为本人工智能&#xff08;第3版&#xff09;通晓六点&#xff0c;明白人工智能是怎么回事基本概念和历史基础知识基于知识的系统高级专题现在和未来安全和编程 人工智能已经是基础学科 学习AI要看的第一本书 人工智能知识对于当…

Unix操作系统的前世今生

Unix是一种多用户、多任务操作系统&#xff0c;最初由AT&T贝尔实验室的肯汤普逊&#xff08;Ken Thompson&#xff09;和丹尼斯里奇&#xff08;Dennis Ritchie&#xff09;等人开发于上世纪70年代初。它被设计成一种通用的操作系统&#xff0c;支持跨多种硬件平台&#xf…

C++入门(详细解读,建议收藏)

&#x1f6a9;C是什么?&#x1f6a9;⛲&#x1f31f;⚡&#x1f966;&#x1f4ac; C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危…

ssm基于Java Web的怀旧唱片售卖系统论文

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装怀旧唱片售卖系统软件来发挥其高效地信息处理的作用&#x…

计算机网络——网络中要解决的问题

1. 从网络管理的角度看 1.1 配置管理 追踪所有部署的硬件和软件资源&#xff0c;包括设备配置和软件版本。 1.2 故障管理​​​​​ 监控设备的运行状态&#xff0c;以确保所有组件都正常工作&#xff0c;以及快速响应和修复任何故障。 1.3 计费管理 监控资源消耗并进行计费…

使用FinalShell连接Linux系统

1.为什么要使用FinalShell连接Linux系统&#xff1f; 如果直接使用VMware上的Linux系统会有很多不方便&#xff1a; 内容的复制粘贴跨越VMware不方便文件的上传、下载跨越VMware不方便 也就是和Linux系统的各类交互&#xff0c;跨越VMware不方便 2.FinalShell下载 FinalSh…

【shell】bash script基础入门及例子(附代码)持续更新

A Bash script is a plain text file which contains a series of commands. Anything you can run normally on the command line can be put into a script ————https://ryanstutorials.net/bash-scripting-tutorial/bash-script.php Reference 教程&#xff1a;一篇教会…

RH850P1X芯片学习笔记-A/D Converter (ADCF)

文章目录 Features of RH850/P1x-C ADCFNumber of UnitsRegister Base AddressClock SupplyInterrupts and DMAHardware ResetExternal Input/Output SignalsVirtual Channel OverviewFunctional OverviewBlock DiagramPhysical Channels, Virtual Channels and Scan Groups Re…

年终总结——平凡又不平凡的2023

前言 总结不知道该如何写起&#xff0c;也不知该如何建立这一篇文章的大致框架&#xff0c;只知道我的2023大概也就分成两大块罢了。说起2023一整年&#xff0c;只能用平凡而又不平凡来形容&#xff0c;平凡在我依旧没有什么太突出的技术点&#xff0c;专业水平也一直处于龟速…

flutter项目初始化

flutter项目初始化 0、flutter 官方插件网址1、flutter项目环境配置2、flutter数据本地存储(shared_preferences)3、GetX 中的数据响应式配合本地存储使用4、Dio 封装使用详解5、EasyLoading的使用6、缓存 keep-alive使用(除了Tabbar,其它的页面、组件都可以使用)7、缓存 …