【刷题】前缀和进阶

在这里插入图片描述
送给大家一句话:
生活坏到一定程度就会好起来,因为它无法更坏。努力过后,才知道许多事情,坚持坚持,就过来了。 – 宫崎骏 《龙猫》

┌(˘⌣˘)ʃ┌(˘⌣˘)ʃ┌(˘⌣˘)ʃ
┌(˘⌣˘)ʃ┌(˘⌣˘)ʃ┌(˘⌣˘)ʃ
┌(˘⌣˘)ʃ┌(˘⌣˘)ʃ┌(˘⌣˘)ʃ


前缀和进阶

  • 1 前言
  • 2 Leetcode 560. 和为 K 的子数组
    • 题目描述
    • 算法思路
  • 3 Leetcode 974. 和可被 K 整除的子数组
    • 题目描述
    • 算法思路
  • 4 Leetcode 525. 连续数组
    • 题目描述
    • 算法思路
  • 5 Leetcode 1314. 矩阵区域和
    • 题目描述
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见

1 前言

今天我们继续加强对前缀和算法。
前缀和算法是对数组进行预处理操作,进而避免大量重复的操作!使得算法性能增强!
适用于对数组有大量重复操作的问题,一维预处理较简单,二维比较复杂,画图分析可以顺利解决!

2 Leetcode 560. 和为 K 的子数组

上链接:560. 和为 K 的子数组

题目描述

在这里插入图片描述
题目是好理解的,我们要在nums数组中找到满足和为K的子数组。注意这里的子数组是连续的!!!不是数学上的子数组哦!!!
来看样例:

  • 输入:nums = [1,1,1], k = 2
  • 输出:2

很明显满足条件的是[1 ,1] 和[1 , 1]。

算法思路

首先最好想的就是暴力枚举算法O(n^2):

  1. 从 0 开始依次枚举子数组的和
  2. 满足条件计数+1

这样毋庸置疑是会超时的。并且会有大量的重复操作,求了许多重复的和。那么是不是就可以进行前缀和优化呢:
我们加入预处理:

int subarraySum(vector<int>& nums, int k) {//sort(nums.begin() , nums.end());int sum[20001] = {0};sum[0] = 0; //0 1 2 3for(int i = 1 ; i <= nums.size() ; i++)sum[i] = sum[i - 1] + nums[i - 1];int count =  0;// for(int i = 0 ; i <= nums.size() ; i++){for(int j = 0 ; j < i ; j++){if(sum[i] - sum[j] == k) count++;}}return count;}

定睛一看,这这这好像时间复杂度还不如暴力算法啊,这个的时间复杂度是O(n^2) + O( n ),也会超时。那这应该怎么处理呢???

双指针(滑动窗口)可以吗?不可以,因为题目并没有说是有序数组,那么就不能保证左右指针移动方向一致!!!

我们引入一个概念:以下标为 i 结尾的子数组 。我们来分析一下

  1. 假如我们枚举到 第 i 个数字,得到了当前的前缀和 sum,
  2. 那么如果想要得到满足和为 k 的子数组,就要寻找前缀和为 sum - k的数组
  3. 那么前缀和为sum - k的数组怎么得到呢???使用哈希算法
  4. 每次的枚举都要对当前的前缀和对应的个数进行 +1
  5. 这样以后调用就方便了
    int subarraySum(vector<int>& nums, int k) {//哈希优化unordered_map<int , int> hash1;// 前缀和 -> 个数//特视情况处理hash1[0] = 1;int sum = 0; int count = 0;for(int i = 0; i < nums.size() ; i++){//记录当前前缀和sum += nums[i];//计数加上[sum - k]对应的个数count += hash1[sum - k];//把当前的前缀和统计上hash1[sum]++;}return count;}

提交看看:过啦!!!

3 Leetcode 974. 和可被 K 整除的子数组

上链接:974. 和可被 K 整除的子数组

题目描述

在这里插入图片描述
这个题目要求我们寻找 和 可以被 k 整除的子数组,很好理解。来看样例:

  • 输入:nums = [4,5,0,-2,-3,1], k = 5
  • 输出:7
  • 解释:有 7 个子数组满足其元素之和可被 k = 5 整除:
    [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]

算法思路

暴力算法就不说了奥,很好想。
这道题与上一道类似,我们可以 使用以下标为 i 结尾的子数组 的方法来解决。但是如何解决判断能否整除呢???
这里要使用数学方法辅助:同余定理:
(sum - x)% k == 0 -> sum % k == x % k
这里面sum是当前的前缀和,x 是前面部分数组的前缀和,那么sum - x就可以理解为子数组的和

既然我们要寻找可以被 k 整除的子数组,就只用找到 前面的前缀和 与 当前前缀和 余数一致 的数组,就可以统计数目了:
大体框架与上道题一致
但是有一个细节需要处理 :C++余数修正
因为数据里有负数,而负数除以一个数的余数在c++中是负数,我们就要对其进行修正,并且还要保证正数的余数正确,所以就要进行一个修正:(sum % k + k) % k 这样就保证了正负数的余数都符合条件了!!!

    int subarraysDivByK(vector<int>& nums, int k) {//前缀和 + 哈希优化//unordered_map<int , int> hash;int hash[10001] = {0};hash[0] = 1;int count = 0;int sum = 0;//同余定理 + C++余数修正for(auto x : nums){sum += x;//判断是否可以整除//(sum - x)% k == 0 -> sum % k == x % kcount += hash[(sum % k + k) % k];hash[(sum % k + k) % k]++;}return count ;}

提交:过啦!!!

4 Leetcode 525. 连续数组

跟上节奏:525. 连续数组

题目描述

在这里插入图片描述
题目很简单,我们需要在给定的数组找到具有相同数量01的最长子数组!!!来看样例:

  • 输入: nums = [0,1,0]
  • 输出: 2
  • 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。

算法思路

暴力算法不在多说,暴力枚举即可。
那么如何使用前缀和来解决问题呢???
我们可以将问题转换一下,把数组中的0都变成-1,然后 具有相同数量01的最长数组的和就是 0 。这样就转换为和为k的最长子数组

整体框架与Leetcode 560. 和为 K 的子数组类似,但是如何计算出最长的子数组。先前我们的哈希表储存的是前缀和 -> 个数,我们这道题使用个数肯定不行,而应该是下标位置,而且是距离最远的位置(也就是该前缀和第一次出现的位置)

    int findMaxLength(vector<int>& nums) {int ans = 0;//前缀和 + 哈希优化//细节处理 记录该位置的前缀和unordered_map<int ,int> hash1; // 前缀和 -> 最远的位置hash1[0] = -1;int sum = 0; for(int i = 0 ; i < nums.size(); i++){//0 转换为 -1sum += nums[i] == 0 ? -1 : 1;//如果哈希表中有 sum 那么直接进行计算if(hash1.count(sum)) ans = max(ans , i - hash1[sum]);//记录的最远的位置else hash1[sum] = i;}return ans;}

提交:过啦!!!

5 Leetcode 1314. 矩阵区域和

家人们,上连接:1314. 矩阵区域和

题目描述

在这里插入图片描述
这道题乍一看:啥玩意儿,怎么没读懂?!
再一看:嗷嗷!原来如此!

区域和是该题的灵魂,来看样例:

  • 输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1
  • 输出:[[12,21,16],[27,45,33],[24,39,28]]

我们有一个3 * 3的mat矩阵,所得的ans矩阵也是 3 * 3。
ans矩阵的ans[ i ][ j ]映射到mat矩阵上是 以 mat[ i ][ j ]为中心 ,向四周扩展 k 个区域的矩阵的和。
在这里插入图片描述
当然必须保证在扩充后的区域在mat中。

那这样就简单了,就转换为二维前缀和了。我们只需要得到左上角的坐标(x1 , y1)和右下角的坐标(x2 , y2)就可以通过公式计算出区域和!!!

我们先来看二维前缀和的预处理如何来做:
在这里插入图片描述
这样需要注意一个小细节,我们进行预处理时,把dp矩阵多开一行一列可以极大的简便我们对边界情况的处理!!!

然后就是对ans矩阵进行计算,那么就要找到左上角的坐标(x1 , y1)和右下角的坐标(x2 , y2)。
为了保证不出界:

  x1 = max(0, i - k ) + 1;y1 = max(0, j - k ) + 1;x2 = min((int)ans.size() - 1, i + k ) + 1;y2 = min((int)ans[0].size() - 1, j + k ) + 1;

为什么要加 + 1呢?因为我们ans 矩阵没有多开一行一列,为了满足与dp满足映射关系,我们需要进行 + 1!!!

找到两个坐标后,就可以来分析计算区域和了
在这里插入图片描述

vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {//二维前缀和//预处理vector<vector<int>> dp(mat.size() + 1, vector<int>(mat[0].size() + 1));for (int i = 1; i < dp.size(); i++){for (int j = 1; j < dp[0].size(); j++){dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + mat[i - 1][j - 1] - dp[i - 1][j - 1];}}vector<vector<int>> ans(mat.size(), vector<int>(mat[0].size()));for (int i = 0; i < ans.size(); i++){for (int j = 0; j < ans[0].size(); j++){//寻找左上角 与 右上角 确保未出界int x1, x2, y1, y2;x1 = max(0, i - k ) + 1;y1 = max(0, j - k ) + 1;x2 = min((int)ans.size() - 1, i + k ) + 1;y2 = min((int)ans[0].size() - 1, j + k ) + 1;ans[i][j] = dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1];}}return ans;}

提交:过啦!!!

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见

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

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

相关文章

RS2105XN功能和参数介绍及PDF资料

RS2105XN 品牌: RUNIC(润石) 封装: MSOP-10 开关电路: 单刀双掷(SPDT) 通道数: 2 工作电压: 1.8V~5.5V 导通时间(Tonmax): 50ns RS2105XN是一款模拟开关芯片。以下是RS2105XN的功能和参数介绍&#xff1a; 功能&#xff1a; 2通道单刀双掷&#xff08;SPDT&#xff09;模拟开关…

基于springboot+mybatis+vue的项目实战之(后端+前后端联调)

步骤&#xff1a; 1、项目准备&#xff1a;创建数据库&#xff08;之前已经创建则忽略&#xff09;&#xff0c;以及数据库连接 2、建立项目结构文件夹 3、编写pojo文件 4、编写mapper文件&#xff0c;并测试sql语句是否正确 5、编写service文件 6、编写controller文件 …

【数据库原理及应用】期末复习汇总高校期末真题试卷09

试卷 一、填空题(每空1分&#xff0c;共10分) 数据的完整性是指数据的________、有效性和相容性。数据模型通常由________、数据操作以及数据约束条件等三要素组成。在关系的有关术语中&#xff0c;关系表中的每一行称作________&#xff0c;每一列称作属性。信息的三种世界是…

C++:多态-虚函数

C 中的多态性是面向对象编程中的一个重要概念&#xff0c;它允许在运行时选择不同的函数实现&#xff0c;以适应不同类型的对象。 多态的种类 编译时多态性&#xff08;Compile-time Polymorphism&#xff09;&#xff1a;也称为静态多态性或早期绑定&#xff0c;指在编译时确…

【网络协议】----IPv6协议报文、地址分类

【网络协议】----IPv6协议简介 【网络协议】----IPv6协议简介IPv6特点IPv4 和 IPv6报文结构IPv6报文格式-拓展报头 IPv6地址分类IPv6地址表示IPv6单播地址可聚合全球单播地址链路本地地址唯一本地地址特殊地址补充 接口标识&#xff08;主机位&#xff09;生成方法通过EUI-64规…

CISCN 2023 初赛

Web unzip 文件上传页面 upload.php页面源码显示了出来 <?php error_reporting(0); highlight_file(__FILE__);$finfo finfo_open(FILEINFO_MIME_TYPE); if (finfo_file($finfo, $_FILES["file"]["tmp_name"]) application/zip){exec(cd /tmp &am…

IP协议,网络层

一、IP协议报文 在网络层最主要的协议是IP协议&#xff0c;网络层的主要任务是进行&#xff1a;1.地址管理 2.路由选择 地址管理&#xff1a;使用一套地址体系&#xff0c;描述互联网中每个设备所处的位置。 IP地址有两个版本&#xff0c;1.IPV4 2.IPV6 &#xff0c;IP…

信奥数据“信息差”,让你惊掉下巴!

✅ 信奥红利分析 暑假信奥赛即将到来&#xff0c;在全国各地赛事也越来越受到重视&#xff0c;但是似乎关于红利这一块各地如何&#xff0c;并没有太多的老师给各位家长分析清楚。 那么今天曹老师就主要给从各位新手家长分析一下信奥红利地区&#xff0c;在开始分析之前请大家看…

使用 MediaMTX 和 FFmpeg 推拉 RTSP 流媒体

实时流传输协议 RTSP&#xff08;Real-Time Streaming Protocol&#xff09;是 TCP/IP 协议体系中的一个应用层协议&#xff0c;由哥伦比亚大学、网景和 RealNetworks 公司提交的 IETF RFC 标准。该协议定义了一对多应用程序如何有效地通过 IP 网络传送多媒体数据。RTSP 在体系…

初始化创建一个webpack项目

新建一个空的工程 -> % mkdir webpack-project 为了方便追踪执行每一个命令&#xff0c;最终产生了哪些变更&#xff0c;将这个空工程初始化成git项目 -> % cd webpack-project/-> % git init Initialized empty Git repository in /Users/lixiang/frontworkspace/…

初探MFC程序混合使用QT

一、背景 随着操作系统国产化替代的趋势越发明显&#xff0c;软件支持国际化、跨平台&#xff0c;已然是必须做的一件事情。原有的软件UI层用的是MFC&#xff0c;将其换成QT&#xff0c;想必是一种较好的方案。对于大型软件&#xff0c;特别是已发布&#xff0c;但还处于不断迭…

C++进阶之路:探索访问限定符、封装与this指针的奥秘(类与对象_上篇)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

数据统计:词频统计、词表生成、排序及计数、词云图生成

文章目录 &#x1f4da;输入及输出&#x1f4da;代码实现 &#x1f4da;输入及输出 输入&#xff1a;读取一个input.txt&#xff0c;其中包含单词及其对应的TED打卡号。 输出 output.txt&#xff1a;包含按频率降序排列的每个单词及其计数&#xff08;这里直接用于后续的词云…

设计模式之单例模式详解

单例模式 描述&#xff1a;单例&#xff08;Singleton&#xff09;模式的定义&#xff1a;指一个类只有一个实例&#xff0c;且该类能自行创建这个实例的一种模式。 核心特点 单例类只有一个实例对象&#xff1b;该单例对象必须由单例类自行创建&#xff1b;单例类对外提供一…

OpenCV 入门(一) —— OpenCV 基础

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

每日两题 / 23. 合并 K 个升序链表 94. 二叉树的中序遍历(LeetCode热题100)

23. 合并 K 个升序链表 - 力扣&#xff08;LeetCode&#xff09; 若lists有k个元素&#xff0c;调用k - 1次&#xff08;两个有序链表的合并&#xff09;即可 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNod…

探索鸿蒙开发:鸿蒙系统如何引领嵌入式技术革新

嵌入式技术已经成为现代社会不可或缺的一部分。而在这个领域&#xff0c;华为凭借其自主研发的鸿蒙操作系统&#xff0c;正悄然引领着一场技术革新的浪潮。本文将探讨鸿蒙开发的特点、优势以及其对嵌入式技术发展的深远影响。 鸿蒙操作系统的特点 鸿蒙&#xff0c;作为华为推…

一键接入电商API数据接口淘宝API通过商品ID、URL采集商品详情页实时数据API接入指南

一键接入电商API数据接口&#xff0c;尤其是淘宝API&#xff0c;通常需要遵循以下步骤&#xff1a; 注册账号&#xff1a;注册接入账号获取Api Key和Api Secret。 选择API&#xff1a;根据需要选择合适的API服务&#xff0c;如通过商品ID或URL采集商品详情页数据的API。 权限…

WPF鼠标拖拽的最佳实现

WPF鼠标拖拽的最佳实现 在很多项目中都会遇到鼠标拖拽控件移动的需求&#xff0c;常见的有从在列表中拖拽列表项移动&#xff0c;拖拽控件移动等。 本文将介绍2种拖拽的简单的实现 列表项的拖拽 本文将使用 gong-wpf-dragdrop 这个github上的库来实现列表的拖拽的效果&…

GitLab使用记录

GitLab 文章目录 1. 常用命令1.1 配置邮箱 用户名1.2 查看配置1.3 基本语法 2. 连接gitlab3. 直接拉去项目 1. 常用命令 1.1 配置邮箱 用户名 git config --global user.name ShangzheChen git config --global user.email 735511377qq.com1.2 查看配置 cat ~/.gitconfig这…