当前位置: 首页 > news >正文

算法专题:前缀和

文章目录

    • Acwing:前缀和示例
    • 2845.统计趣味子数组的数目
      • 思路
      • 容易理解的写法:前缀和+两层循环
        • 存在问题:超时
      • 优化写法:两数之和思路,转换为哈希表

前缀和,就是求数组中某一段的所有元素的和

求子数组中某一段数字的元素和,只需要转换成两个数字的差值就可以了。

注意:

  • 只能求连续某一段区间的元素和
  • 一般来说前缀和需要在前面加一个0,因为表示成两个数字的差的话,如果前面不加0,带有第一个数字的元素和无法表示成差值,例如下图

在这里插入图片描述

Acwing:前缀和示例

在这里插入图片描述

  • 前缀和注意:需要在最前面加上一个0,所以前缀和数组大小是nums.size()+1
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;int main()
{int n, m, l, r;scanf("%d%d", &n, &m);int a[n], sum[n + 1];     // s设置为n+1是为了后面计算方便for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);sum[0] = 0;for (int i = 0; i < n; i ++ ) sum[i + 1] = sum[i] + a[i];while (m -- ) {scanf("%d%d", &l, &r);printf("%d\n", sum[r] - sum[l - 1]);	// 这里的l和r是1~n范围}return 0;
}
  1. 读入两个整数 nmn 是数组 a 的大小,m 是查询的数量。
  2. 定义数组 asuma 用于存储输入的整数序列,sum 用于存储前缀和。
  3. 初始化 sum[0] 为0。
  4. 使用循环计算 sum 数组,其中 sum[i] 存储了数组 a 的前 i 个元素的和。
  5. 循环进行 m 次查询,每次查询读入两个整数 lr,然后输出区间 [l, r] 的和。这个和可以通过 sum[r] - sum[l - 1] 很快得到。注意,这里的 lr 是1-based,也就是从1开始的,而数组索引是0-based所以可以直接用sum[r]-sum[l-1],因为r本身已经是对应的下标+1了

代码示例中的 sum[r] - sum[l - 1] 是核心点。为了理解它,考虑下面的例子:

a:     2   3   4   5
sum:  0   2   5   9  14

为了得到 [2, 4]这里的下标r和l是从1开始的)子区间和 (即 3 + 4 + 5),我们可以使用 sum[4] - sum[2 - 1],结果为 12。

2845.统计趣味子数组的数目

给你一个下标从 0 开始的整数数组 nums ,以及整数 modulo 和整数 k

请你找出并统计数组中 趣味子数组 的数目。

如果 子数组 nums[l..r] 满足下述条件,则称其为 趣味子数组

  • 在范围 [l, r] 内,设 cnt 为满足 nums[i] % modulo == k 的索引 i 的数量。并且 cnt % modulo == k

以整数形式表示并返回趣味子数组的数目。

**注意:**子数组是数组中的一个连续非空的元素序列。

示例 1:

输入:nums = [3,2,4], modulo = 2, k = 1
输出:3
解释:在这个示例中,趣味子数组分别是: 
子数组 nums[0..0] ,也就是 [3] 。 
- 在范围 [0, 0] 内,只存在 1 个下标 i = 0 满足 nums[i] % modulo == k 。
- 因此 cnt = 1 ,且 cnt % modulo == k 。
子数组 nums[0..1] ,也就是 [3,2] 。
- 在范围 [0, 1] 内,只存在 1 个下标 i = 0 满足 nums[i] % modulo == k 。
- 因此 cnt = 1 ,且 cnt % modulo == k 。
子数组 nums[0..2] ,也就是 [3,2,4] 。
- 在范围 [0, 2] 内,只存在 1 个下标 i = 0 满足 nums[i] % modulo == k 。
- 因此 cnt = 1 ,且 cnt % modulo == k 。
可以证明不存在其他趣味子数组。因此,答案为 3 。

示例 2:

输入:nums = [3,1,9,6], modulo = 3, k = 0
输出:2
解释:在这个示例中,趣味子数组分别是: 
子数组 nums[0..3] ,也就是 [3,1,9,6] 。
- 在范围 [0, 3] 内,只存在 3 个下标 i = 0, 2, 3 满足 nums[i] % modulo == k 。
- 因此 cnt = 3 ,且 cnt % modulo == k 。
子数组 nums[1..1] ,也就是 [1] 。
- 在范围 [1, 1] 内,不存在下标满足 nums[i] % modulo == k 。
- 因此 cnt = 0 ,且 cnt % modulo == k 。
可以证明不存在其他趣味子数组,因此答案为 2 。

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^9
  • 1 <= modulo <= 10^9
  • 0 <= k < modulo

思路

首先思路就是运用前缀和,单独开一个x数组遍历所有的nums[i],满足条件计数为1,不满足条件计数为0。

这样的话,子数组[l,r]内满足条件的数字个数,直接就是子数组对应的x数组区间的和

容易理解的写法:前缀和+两层循环

#include <vector>class Solution {
public:long countInterestingSubarrays(std::vector<int>& nums, int modulo, int k) {int n = nums.size();// 创建一个数组x来标记哪些数字模`modulo`后等于kstd::vector<int> x(n, 0);// 创建一个前缀和数组std::vector<int> sum(n + 1, 0);// ----------- 前缀和计算开始 -----------for (int i = 0; i < n; ++i) {// 如果当前数字模`modulo`后等于k,则在x数组中的对应位置标记为1if (nums[i] % modulo == k) x[i] = 1;// 计算前缀和:当前位置的前缀和等于上一个位置的前缀和加上x数组中的当前值sum[i + 1] = sum[i] + x[i];}// ----------- 前缀和计算结束 -----------// 初始化答案为0long ans = 0;// 使用两重循环来检查所有可能的子数组和for (int l = 0; l < n; ++l) {               // 子数组的开始位置for (int r = l + 1; r <= n; ++r) {      // 子数组的结束位置// 如果子数组的和模`modulo`后等于k,则增加答案的值if ((sum[r] - sum[l]) % modulo == k) ans++;}}// 返回答案return ans;}
};

存在问题:超时

这种写法因为子数组两边都不定,会超时,时间复杂度是O(n^2)。

在这里插入图片描述

优化写法:两数之和思路,转换为哈希表

因为上面写法出现了超时,我们可以用类似 两数之和 的套路,来优化时间复杂度,用map来减少一层循环

  • 两数之和的优化方法是,遍历到nums[i]的时候,先看看target-nums[i]是不是已经在map里面了如果在直接返回,不在就加到map里面,继续遍历数字。遍历完了数组之后一定会收集所有的相加=目标和的两数组合。

  • 本题的优化方法是,我们遍历sum[r]的时候,找满足sum[r] - sum[l]) % modulo == k条件的sum[l]是不是已经在哈希表里面了。哈希表map的作用是存放已经枚举过的sum

#include <vector>
#include <unordered_map>class Solution {
public:long countInterestingSubarrays(std::vector<int>& nums, int modulo, int k) {int n = nums.size();// x是原始数组,sum是前缀和数组std::vector<int> x(n, 0);std::vector<int> sum(n + 1, 0);// 使用unordered_map存储各个余数的位置数量std::unordered_map<int, int> cnt;cnt[0] = 1;long ans = 0;for (int i = 0; i < n; ++i) {if (nums[i] % modulo == k) x[i] = 1;// 计算前缀和sum[i + 1] = (sum[i] + x[i]) % modulo;int r = sum[i + 1];// 此处的索引就是在找满足条件的sum[l],r就是之前版本的sum[r]//需要满足的式子是(sum[r] - sum[l]) % modulo == k//这里+modulo的目的是为了防止r-k是负数,+m再取余,结果还是0不会影响ans += cnt[(r - k + modulo) % modulo];// 更新哈希表中的计数,这里是在更新sum[r]进哈希表(对应之前版本)cnt[r]++;}return ans;}
};

相关文章:

算法专题:前缀和

文章目录 Acwing&#xff1a;前缀和示例2845.统计趣味子数组的数目思路容易理解的写法&#xff1a;前缀和两层循环存在问题&#xff1a;超时 优化写法&#xff1a;两数之和思路&#xff0c;转换为哈希表 前缀和&#xff0c;就是求数组中某一段的所有元素的和。 求子数组中某一…...

bs4库爬取天气预报

Python不仅用于网站开发&#xff0c;数据分析&#xff0c;图像处理&#xff0c;也常用于爬虫技术方向&#xff0c;最近学习了解下&#xff0c;爬虫技术入门一般先使用bs4库&#xff0c;爬取天气预报简单尝试下。 第一步&#xff1a;首先选定目标网站地址 网上查询&#xff0c…...

l8-d8 TCP并发实现

一、TCP多进程并发 1.地址快速重用 先退出服务端&#xff0c;后退出客户端&#xff0c;则服务端会出现以下错误&#xff1a; 地址仍在使用中 解决方法&#xff1a; /*地址快速重用*/ int flag1,len sizeof (int); if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &a…...

编写中间件以用于 Express 应用程序

概述 中间件函数能够访问请求对象 (req)、响应对象 (res) 以及应用程序的请求/响应循环中的下一个中间件函数。下一个中间件函数通常由名为 next 的变量来表示。 中间件函数可以执行以下任务&#xff1a; 执行任何代码。对请求和响应对象进行更改。结束请求/响应循环。调用堆…...

【2023年数学建模国赛】D题解题思路

2023年数学建模国赛D题解题思路 为了解决问题1、问题2和问题3&#xff0c;我们可以采用动态规划方法来制定生产计划&#xff0c;考虑了不确定性因素和多种可能情况的预案集。首先&#xff0c;我们需要定义一些变量和符号&#xff1a; T T T&#xff1a;总的养殖周期&#xff0…...

python爬虫之正则表达式学习

网络安全离不开脚本和工具的开发&#xff0c;python很多又需要正则表达式。 这是一个很好的学习正则表达式的项目 https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md 基本匹配 正则表达式其实就是在执行搜索时的格式&#xff0c;它由一些字…...

智慧能源方案:TSINGSEE青犀AI算法中台在能源行业的应用

一、方案背景 互联网、物联网、人工智能等新一代信息技术引领新一轮产业革命&#xff0c;加快能源革命步伐。尤其是随着人工智能技术的不断发展&#xff0c;AI智能检测与识别技术在能源行业的应用也越来越广泛。与此同时&#xff0c;国家出台多项政策&#xff0c;将智慧能源纳…...

达梦数据库awr报告收集

1、找出快照点snap_id与时间的对应关系 SYS.WRM$_SNAPSHOT表中记录了快照点snap_id与时间的对应关系 例如如下语句可以得出2023-09-04这一天各个时间点对应的快照点snap_id select snap_id,end_interval_time from SYS.WRM$_SNAPSHOT where end_interval_time between to…...

c语言练习43:深入理解strcmp

深入理解strcmp strcmp的主要功能是用来比较两个字符串 模拟实现strcmp 比较两个字符串对应位置上的大小 按字典序进行比较 例如&#xff1a; 输入&#xff1a;abc abc 输出&#xff1a;0 输入&#xff1a;abc ab 输出&#xff1a;>0的数 输入&#xff1a;ab abc …...

NUC980webServer开发

目录 1.RTL8189FTV驱动移植 2.wifi配置工具hostapd移植 1.openssl-1.0.2r交叉编译 2.libnl-3.2.25.tar.gz交叉编译 3.hostapd-2.9.tar.gz交叉编译 4.移植相关工具到开发板 1.RTL8189FTV驱动移植 1. 把驱动文件源码放在linux源码的drivers/net/wireless/realtek/rtlwifi/目录…...

驱动开发--day2

实现三盏灯的控制&#xff0c;编写应用程序测试 head.h #ifndef __HEAD_H__ #define __HEAD_H__#define LED1_MODER 0X50006000 #define LED1_ODR 0X50006014 #define LED1_RCC 0X50000A28#define LED2_MODER 0X50007000 #define LED2_ODR 0X50007014#endif mychrdev.c #inc…...

用户促活留存新方式——在APP中嵌入小游戏

随着APP同类产品的不断出现&#xff0c;APP开发者们面临着激烈的竞争&#xff0c;很多APP下载后被新的APP取代&#xff0c;获客成本越来越高。同时开发者还会面临用户粘性差、忠诚度低、用完即走、留存困难&#xff0c;商业化价值被大大缩减。 在APP中植入小游戏来提高用户活跃…...

MySQL 8.0.34(x64)安装笔记

一、背景 从MySQL 5.6到5.7&#xff0c;再到8.0&#xff0c;版本的跳跃不可谓不大。安装、配置的差别也不可谓不大&#xff0c;特此备忘。 二、过程 &#xff08;1&#xff09;获取MySQL 8.0社区版&#xff08;MySQL Community Server&#xff09;   从 官网 字样 “MySQL …...

物流供应商实现供应链自动化的3种方法

当前影响供应链的全球性问题(如新冠肺炎疫情)正在推动许多物流供应商重新评估和简化其流程。运输协调中的摩擦只会加剧供应商无法控制的现有延误和风险。值得庆幸的是&#xff0c;供应链专业人员可以通过端到端的供应链自动化消除延迟&#xff0c;简化与合作伙伴的沟通&#xf…...

Mysql更新时间列只改日期为指定日期不更改时间

场景 Mysql分表后同结构不同名称表之间复制数据以及Update语句只更新日期加减不更改时间&#xff1a; Mysql分表后同结构不同名称表之间复制数据以及Update语句只更新日期加减不更改时间_霸道流氓气质的博客-CSDN博客 上面通过如下方式实现日期列增加指定天数。 UPDATE bus…...

实时测试工具 Visual Studio 扩展 NCrunch 4.18 Crack

NCrunch Visual Studio 扩展 .NET 的终极实时测试工具 在编码时查看实时测试结果和内联指标。 下载v4.18 发布于 2023 年 7 月 17 日 跳过视频至&#xff1a; 代码覆盖率 指标 分布式处理 配置 发动机模式 Visual Studio 自动并发测试 NCrunch 是一个完全自动化的测试扩展&a…...

Neo4j 基本语法

一、基本语法 1、新建节点 &#xff08;1&#xff09;基本语法&#xff1a; () 代表节点 示例&#xff1a; CREATE (u:User {uid:970939424 }) // 节点类型为User&#xff0c;属性值为uid970939424CREATE (u:Round {rid:7194842697444819113 }) // 节点类型为Rou…...

docker常见面试题

1.什么是docker docker是一个容器化平台&#xff0c;类似于一个集装箱&#xff0c;集装箱与集装箱之间互不影响&#xff0c;docker平台就是一个软件集装箱平台&#xff0c;我们可以构建应用程序&#xff0c;将其所有的依赖打包到一个容器中&#xff0c;然后就很方便的可以在其…...

静态路由:配置和使用详解

文章目录 一、静态路由的配置和使用详解1. 配置要点1.1 点到点接口配置1.2 以太网接口配置 2. 默认路由3. 静态路由的配置命令4. 静态路由实现路由备份和负载分担 二、静态路由的优先级和比较1. 静态路由的优先级设置2. 静态路由与动态路由的比较2.1 静态路由优缺点2.2 动态路由…...

玩转Mysql系列 - 第15篇:详解视图

这是Mysql系列第15篇。 环境&#xff1a;mysql5.7.25&#xff0c;cmd命令中进行演示。 需求背景 电商公司领导说&#xff1a;给我统计一下&#xff1a;当月订单总金额、订单量、男女订单占比等信息&#xff0c;我们啪啦啪啦写了一堆很复杂的sql&#xff0c;然后发给领导。 …...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...