算法之 前缀和

news2025/4/23 21:57:25

文章目录

  • 前缀和基础
    • 3427.变长子数组求和
  • 前缀和与哈希表
    • 1524.和为奇数的子数组数目
  • 距离和
    • 1685.有序数组中绝对值之和
  • 前缀异或和
    • 1177.构建回文串检测
  • 其他一维前缀和
    • 1310.子数组异或查询
  • 二维前缀和
    • 1314.矩阵区域和

  • 前缀和,就是定义pre[i] 为nums的前i个元素的和值,一般pre数组长度会=n+1,这样在计算的nums数组中下标i到j的情况的时候,直接就可以使用pre[j+1]-pre[i],如果找的是第i个到第j个,那么就是pre[j]-pre[i-1]
  • 转化为第几个会好理解一点
  • 所以得根据题目求解的是下标还是第几个确定具体的计算公式
  • 前缀和与哈希表:注意第一个元素是否加入哈希表!
  • 二维前缀和: 求解下标为(x1,y1),(x2,y2)二维区间之间的区间和,转化为第几个,那么对应的公式就是ans = pre[x2+1][y2+1] - pre[x1][y2+1] - pre[x2+1][y1] + pre[x1][y1],开始的时候求解的区间前缀的公式是pre[i+1][j+1] = pre[i][j+1] + pre[i+1][j] - pre[i][j] + nums[i][j]

前缀和基础

3427.变长子数组求和

3427.变长子数组求和

在这里插入图片描述

  • 求解的是下标问题,所以是pre[j+1] - pre[i]类型
class Solution:
    def subarraySum(self, nums: List[int]) -> int:
        # 前缀和的问题
        n = len(nums)
        pre = [0]*(n+1)
        for i in range(n):
            pre[i+1] = pre[i] + nums[i]
        ans = 0
        for i in range(n):
            start = max(0,i-nums[i])
            ans += pre[i+1] - pre[start] 
        return ans

前缀和与哈希表

1524.和为奇数的子数组数目

1524.和为奇数的子数组数目

在这里插入图片描述

  • 使用哈希表+前缀和,要注意这个前缀和的第一个也要加入哈希表
class Solution:
    def numOfSubarrays(self, arr: List[int]) -> int:
        # 直接用哈希表存储
        mod = 10**9 + 7
        store = [0,0]
        n = len(arr)
        # 使用前缀和
        pre = [0]*(n+1)
        for i in range(n):
            pre[i+1] = pre[i] + arr[i]
        ans = 0
        for i in range(n+1):
            if pre[i] % 2==0:
                ans = ans + store[1]
                store[0] = store[0] + 1
            else:
                ans = ans + store[0]
                store[1] = store[1] + 1
        return ans % mod

距离和

1685.有序数组中绝对值之和

1685.有序数组中绝对值之和

在这里插入图片描述

  • 由于是有序的,所以计算的公式可以拆开,然后就会发现很多得使用到区间和的问题

博主分析

class Solution:
    def getSumAbsoluteDifferences(self, nums: List[int]) -> List[int]:
        # 由于是有序的,所以可以考虑直接拆分公式,然后使用前缀和
        # 原本情况下,nums[i] - nums[j] 前面的情况,当 i的时候,前面有i个也就是
        # nums[i] * i - 前 nums[0] + ··· + nums[i-1] 也就是 pre[i]
        # n - 1 - (i+1) + 1 = n - i  -1 个 
        # 后续的情况就是 nums[j] - nums[i] ,也就是 nums[i+1] + ··· + nums[n-1] - 
        # 第 i + 2个

        n = len(nums)
        pre = [0]*(n+1)
        for i in range(n):
            pre[i+1] = pre[i] + nums[i]
        ans = [0]*n
        for i in range(n):
            ans[i] = i * nums[i] - pre[i] - (n-i-1)* nums[i] +  pre[n] - pre[i+1]
        return ans  

前缀异或和

1177.构建回文串检测

1177.构建回文串检测
在这里插入图片描述

  • 可以看到,是求解区间的情况,并且可以重新排列,并且是最多K次替换成任何小写英文字母,对于回文串的问题,由于是可以重新排列,所以我们得统计每种字母出现的次数,因为当字母出现的次数是偶数的时候,我们就可以对称分布,当是奇数的时候,如果出现一个奇数,那我们可以直接放最中间,如果出现2个奇数,就得改变其中一个即可,以此类推我们只需统计区间内26个字母出现的奇数的次数num,那么对应结果就是num//2
class Solution:
    def canMakePaliQueries(self, s: str, queries: List[List[int]]) -> List[bool]:
        # 使用前缀和计算 26种字母出现的次数
        n = len(s)
        pre = [[0]*26 for i in range(n+1)]
        # 计数方式
        for i in range(n):
            tar = ord(s[i]) - ord("a")
            for j in range(26):
                if j == tar:
                    pre[i+1][j] = pre[i][j] + 1
                else:
                    pre[i+1][j] = pre[i][j]
        # 统计完成 
        # 开始遍历
        m = len(queries)
        ans = [0]*m 
        for i in range(m):
            odd = 0
            left,right,k = queries[i][0],queries[i][1],queries[i][2]
            for j in range(26):
                # left 是下标,也就是第left+1个,那么就是对应pre[left],right是对应这个第right+1个,pre[right+1]
                if (pre[right+1][j]%2 == 1 and  pre[left][j]%2 == 0) or (pre[right+1][j]%2 == 0 and  pre[left][j]%2 == 1):
                    odd += 1
            # 判断是否超过可以修改的次数
            if odd // 2 <= k:
                ans[i] = True
            else:
                ans[i] = False
        return ans
  • 当然,这个奇数偶数的情况其实可以用异或的情况表示,也就是开始的时候都是0,但是该字母出现一次的时候,我们就用上一个次数前缀和异或1,否则就是异或0
class Solution:
    def canMakePaliQueries(self, s: str, queries: List[List[int]]) -> List[bool]:
        # 使用前缀和计算 26种字母出现的次数
        n = len(s)
        pre = [[0]*26 for i in range(n+1)]
        # 计数方式
        for i in range(n):
            tar = ord(s[i]) - ord("a")
            for j in range(26):
                if j == tar:
                    pre[i+1][j] = pre[i][j] ^ 1
                else:
                    pre[i+1][j] = pre[i][j] ^ 0
        # 统计完成 
        # 开始遍历
        m = len(queries)
        ans = [0]*m 
        for i in range(m):
            odd = 0
            left,right,k = queries[i][0],queries[i][1],queries[i][2]
            for j in range(26):
                # left 是下标,也就是第left+1个,那么就是对应pre[left],right是对应这个第right+1个,pre[right+1]
                #if (pre[right+1][j]%2 == 1 and  pre[left][j]%2 == 0) or (pre[right+1][j]%2 == 0 and  pre[left][j]%2 == 1):
                if pre[right+1][j]%2 ^ pre[left][j]%2 == 1:
                    odd += 1
            # 判断是否超过可以修改的次数
            if odd // 2 <= k:
                ans[i] = True
            else:
                ans[i] = False
        return ans

其他一维前缀和

1310.子数组异或查询

1310.子数组异或查询

在这里插入图片描述

  • 异或的性质要掌握 a^b = k,那么就可以推出a = k ^ b
  • 只需记录异或前缀即可,就类似于正常的求解区间和一样
class Solution:
    def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]:

        # 前缀异或和
        n = len(arr)
        pre = [0]*(n+1)
        for i in range(n):
            # pre[i] 表示前i个元素的异或和
            pre[i+1] = pre[i] ^ arr[i]
        m = len(queries)
        ans = [0]*m
        for i in range(m):
            left,right = queries[i][0],queries[i][1]
            # 对应的是第left+1到right+1的异或区间值,对应就是pre[right+1] - pre[left]
            ans[i] = pre[right+1] ^ pre[left]
        return ans

二维前缀和

1314.矩阵区域和

1314.矩阵区域和

在这里插入图片描述

  • 二维前缀和

在这里插入图片描述

class Solution:
    def matrixBlockSum(self, mat: List[List[int]], k: int) -> List[List[int]]:
        # 二维区间前缀和
        m,n = len(mat),len(mat[0])
        # 肯定不可能按照题目的意思直接构造
        # 还是按照二维前缀和的思想,求解答案

        pre = [[0]*(n+1) for _ in range(m+1)]
        for i in range(m):
            for j in range(n):
                # pre[i][j] 表示i列,前j行所围成的区间和
                pre[i+1][j+1] = pre[i+1][j] + pre[i][j+1] - pre[i][j] + mat[i][j]
        # 求解完,然后进行求解答案
        ans = [[0]*n for i in range(m)]
        for i in range(m):
            for j in range(n):
                # 先求解出下标的问题
                x1,x2 = max(0,i-k),min(m-1,i+k)
                y1,y2 = max(0,j-k),min(n-1,j+k)
                # 这个是下标问题,所以是对应的是
                ans[i][j] = pre[x2+1][y2+1] - pre[x2+1][y1] - pre[x1][y2+1] + pre[x1][y1]
        return ans

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

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

相关文章

机器视觉运动控制一体机在天地盖同步跟随贴合解决方案

市场应用背景 纸盒天地盖是一种包装形式&#xff0c;广泛应用于消费电子、食品礼盒、奢侈品及化妆品等领域。其采用高强度纸板&#xff0c;经过预组装处理&#xff0c;结构坚固稳定&#xff0c;能有效保护产品并提升品牌形象。随着包装行业快速发展&#xff0c;市场对天地盖的…

B站文生视频模型工程实践

1.前言 近年来&#xff0c;AI 内容生成&#xff08;AIGC&#xff09;领域的快速发展令人雀跃&#xff0c;OpenAI 在 2023 年初推出大型语言模型&#xff08;LLM&#xff09;GPT-4 受到了学术界和工业界的极大关注。OpenAI 随后在 2024 年初推出文生视频&#xff08;T2V&#xf…

嵌入式开发:傅里叶变换(5):基于STM32,实现CMSIS中的DSP库

目录 步骤 1&#xff1a;准备工作 步骤 2&#xff1a;创建 Keil 项目&#xff0c;并配置工程 步骤 3&#xff1a;在MDK工程上添加 CMSIS-DSP 库 步骤 5&#xff1a;编写代码 步骤 6&#xff1a;配置时钟和优化 步骤 7&#xff1a;调试与验证 步骤 8&#xff1a;优化和调…

【人工智能】GPT-4 vs DeepSeek-R1:谁主导了2025年的AI技术竞争?

前言 2025年&#xff0c;人工智能技术将迎来更加激烈的竞争。随着OpenAI的GPT-4和中国初创公司DeepSeek的DeepSeek-R1在全球范围内崭露头角&#xff0c;AI技术的竞争格局开始发生变化。这篇文章将详细对比这两款AI模型&#xff0c;从技术背景、应用领域、性能、成本效益等多个方…

【Python项目】基于深度学习的车辆特征分析系统

【Python项目】基于深度学习的车辆特征分析系统 技术简介&#xff1a;采用Python技术、MySQL数据库、卷积神经网络&#xff08;CNN&#xff09;等实现。 系统简介&#xff1a;该系统基于深度学习技术&#xff0c;特别是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;用…

【江科大STM32】TIM输入捕获模式PWMI模式测频率

一、输入捕获测频率 接线图&#xff1a; 测信号的输入引脚为PA6&#xff0c;信号从PA6进来&#xff0c;待测的PWM信号也是STM32自己生成的&#xff0c;输出引脚是PA0&#xff0c;所以接线这里直接用一根线将PA0引到PA6就可以了。 如果有信号发生器的话&#xff0c;也可以设置成…

K8S学习之基础十六:k8s中Deployment更新策略

滚动更新 滚动更新是一种自动化程度较高的发布方式、用户体验比较平滑、是目前成熟型技术组织采用的主流发布方式&#xff0c;一次滚动发布一般有若干发布批次组成&#xff0c;每批的数量一般都是可配置的&#xff0c;可通过发布模板定义&#xff0c;例如第一批10%&#xff0c…

EtherNet/IP转Modbus解析基于网关模块的罗克韦尔PLC与Modbus上位机协议转换通讯案例

在工业自动化控制系统中&#xff0c;常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中&#xff0c;客户现场采用了 AB PLC&#xff0c;但需要控制的变频器仅支持 Modbus 协议。为了实现 AB PLC 对变频器的有效控制与监控&#xff0c;引入了捷米特 JM-EIP-RTU 网…

Devart dbForge Studio for MySQL Enterprise 9.0.338高效数据库管理工具

Devart dbForge Studio for MySQL Enterprise 9.0.338 是一款功能强大的 MySQL 数据库管理工具&#xff0c;专为数据库开发人员和管理员设计。它提供了丰富的功能&#xff0c;帮助用户更高效地管理、开发和维护 MySQL 数据库 Devart dbForge Studio for MySQL Enterprise 9.0.…

STM32-USART串口数据包

一&#xff1a;HEX数据包发送 1.为了收发数据包&#xff0c;先定义两个缓存区的数组 &#xff0c;这4个数据只存储发送或者接收的载荷数据&#xff0c;包头和包尾不存 uint8_t Serial_TxPacket[4]; uint8_t Serial_RxPacket[4]; uint8_t Serial_RxFlag;//接收一个数据包就置F…

轻闪PDF(Windows傲软PDF编辑软件)2.15.2中文安装版

前言 轻闪pdf是个很好用的文件编辑软件&#xff0c;它能让大家编辑文档变得更简单、更快。这个软件特别厉害&#xff0c;能从照片里直接“抓”出文字来&#xff0c;让你打字变得更轻松。而且&#xff0c;它还能把PDF文件变成其他格式的文件&#xff0c;反过来也行。还有啊&…

Python-07PDF转Word

2025-03-04-PDF转Word DeepSeek等大模型从来都不是简单的写一个静态博客这么肤浅&#xff08;太多博主都只讲这个内容了&#xff09;借助全网大神的奇思妙想&#xff0c;拓展我狭隘的思维边界。 文章目录 2025-03-04-PDF转Word [toc]1-参考网址2-学习要点3-核心逻辑4-核心代码 …

Arcgis中添加脚本工具箱

文章目录 准备资料1、打开arcmap2、找到目录窗口3、复制粘贴工具箱的路径4、添加或者确认python脚本路径准备资料 (1)工具箱 (2)python脚本 1、打开arcmap 2、找到目录窗口 3、复制粘贴工具箱的路径 4、添加或者确认python脚本路径 脚本上右键属性(注意:脚本内容和路径…

拥抱健康养生,开启活力生活

在快节奏的现代生活中&#xff0c;健康养生已成为人们关注的焦点&#xff0c;它不仅是对身体的呵护&#xff0c;更是一种积极的生活态度。 合理饮食是健康养生的基石。我们应秉持均衡膳食的理念&#xff0c;谷物、蔬菜、水果、蛋白质类食物一个都不能少。每天保证足够的蔬菜摄入…

字节跳动AI原生编程工具Trae和百度“三大开发神器”AgentBuilder、AppBuilder、ModelBuilder的区别是?

字节跳动AI编程工具Trae与百度"三大开发神器"&#xff08;AgentBuilder、AppBuilder、ModelBuilder&#xff09;在定位、功能架构和技术路线上存在显著差异&#xff0c;具体区别如下&#xff1a; 一、核心定位差异 Trae&#xff1a;AI原生集成开发环境&#xff08;AI…

【MySQL】第十二弹---表连接详解:从内连接到外连接

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】 目录 1.表的内连和外连 1.1 内连接 1.2 外连接 1.2.1 左外连接 1.2.1 右外连接 1.3 实战OJ 1.表的内连和外连 表的连接…

审批流AntV框架蚂蚁数据可视化X6饼图(附注释)

大家好&#xff0c;这次使用的是AntV的蚂蚁数据可视化X6框架&#xff0c;类似于审批流的场景等&#xff0c;代码如下&#xff1a; X6框架参考网址&#xff1a;https://x6.antv.vision/zh/examples/showcase/practices#bpmn 可以进入该网址&#xff0c;直接复制下方代码进行调试…

【SpringBoot】深入解析 Maven 的操作与配置

Maven 1.什么是Maven? Maven是一个项目管理工具&#xff0c;通过pom.xml文件的配置获取jar包&#xff0c;而不用手动去添加jar包&#xff1b; 2. 创建一个Maven项目 IDEA本身已经集成了Maven&#xff0c;我们可以直接使用&#xff0c;无需安装 以下截图的idea版本为&#xff…

搭建一个简单的node服务,模拟后端接口

目录 一、查看是否安装了node和npm 二、创建一个文件夹&#xff0c;用于放你的node服务代码 三、初始化一个package.json 四、安装 Express&#xff08;快速搭建服务的框架&#xff09; 五、创建serve.js 六、运行服务即可 七、测试接口 法一&#xff1a;使用 curl 法…

【落羽的落羽 C++】C++入门基础:引用,内联,nullptr

文章目录 一、引用1. 引用的概念2. 引用的特点3. 引用的使用4. const引用5. 引用和指针 二、inline内联三、nullptr 一、引用 1. 引用的概念 引用是C中的一个较为重要的概念。它是给已存在变量取的“别名”&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引…