【数据结构与算法】常用算法 前缀和

 🎉🎉欢迎光临🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟特别推荐给大家我的最新专栏《数据结构与算法:初学者入门指南》📘📘

本专栏纯属为爱发电永久免费!!!

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽http://suzee.blog.csdn.net

281d83d3df1a4544bdd00fdadf50950b.png

 

 

引言:


前缀和算法就是一种常用的算法,用于快速计算数组或序列中某一区间的和。它在很多问题中都有广泛的应用,例如求解子数组的最大和、区间和等。本文将介绍前缀和算法的原理及其应用。

  1. 问题背景:
    在很多计算问题中,我们需要频繁地计算数组或序列中某一区间的和。如果每次都遍历区间中的元素进行累加,时间复杂度会很高,效率低下。因此,我们需要一种更高效的方法来解决这个问题。

  2. 前缀和算法的作用:
    前缀和算法可以将数组或序列中的每个位置的元素累加起来,得到一个前缀和数组。利用前缀和数组,我们可以在O(1)的时间复杂度内计算任意区间的和,从而提高计算效率。

2.1 前缀和的定义:


对于一个给定的数组或序列,我们定义前缀和数组prefixSum,其中prefixSum[i]表示原数组中前i个元素的和。即prefixSum[i] = nums[0] + nums[1] + ... + nums[i-1]。特别地,prefixSum[0] = 0。

2.2 计算前缀和数组:


为了计算前缀和数组,我们可以从第一个元素开始遍历原数组,对于每个位置i,将前i个元素的和保存到prefixSum[i]中。具体的计算方法如下:

prefixSum[0] = 0
for i from 1 to n:
    prefixSum[i] = prefixSum[i-1] + nums[i-1]

其中,n表示数组的长度,nums表示原数组。

2.3 利用前缀和数组计算区间和:


利用前缀和数组,我们可以在O(1)的时间复杂度内计算任意区间的和。对于给定的区间[left, right],其中left表示区间的起始位置,right表示区间的结束位置,区间和可以通过前缀和数组计算得到:

sum[left, right] = prefixSum[right+1] - prefixSum[left]

其中,prefixSum[right+1]表示前right+1个元素的和,prefixSum[left]表示前left个元素的和。通过这个计算公式,我们可以快速得到任意区间的和。

3.1 子数组和的计算

def prefix_sum(nums):
    n = len(nums)
    prefix = [0] * (n + 1)
    
    for i in range(1, n + 1):
        prefix[i] = prefix[i - 1] + nums[i - 1]
    
    return prefix

def subarray_sum(nums, start, end):
    prefix = prefix_sum(nums)
    return prefix[end + 1] - prefix[start]

使用 prefix_sum 函数可以计算原始数组的前缀和数组 prefix。然后,通过计算 prefix[end + 1] - prefix[start],就可以得到从下标 start 到下标 end 的子数组和。

3.2 区间和的查询

def range_sum(prefix, start, end):
    return prefix[end + 1] - prefix[start]

在区间和的查询中,我们不需要每次都重新计算前缀和数组。我们可以直接使用已经计算好的前缀和数组 prefix,通过计算 prefix[end + 1] - prefix[start],即可得到从下标 start 到下标 end 的区间和。

3.3 数组元素的更新和查询

def update(prefix, index, value):
    prefix[index + 1] += value

def query(prefix, index):
    return prefix[index + 1]

在数组元素的更新和查询中,我们可以直接通过修改前缀和数组 prefix 中的相应位置来实现。通过 prefix[index + 1] 可以查询下标 index 处的数组元素值,通过 prefix[index + 1] += value 可以更新下标 index 处的数组元素值。

4.1 前缀和数组的空间优化

def prefix_sum(nums):
    n = len(nums)
    prefix = [0] * n
    prefix[0] = nums[0]
    
    for i in range(1, n):
        prefix[i] = prefix[i - 1] + nums[i]
    
    return prefix

def subarray_sum(nums, start, end):
    prefix = prefix_sum(nums)
    if start == 0:
        return prefix[end]
    else:
        return prefix[end] - prefix[start - 1]

在前缀和数组的空间优化中,我们可以直接在原始数组 nums 上进行操作,而不需要额外的前缀和数组。在计算子数组和时,通过 prefix[end] - prefix[start - 1] 可以得到从下标 start 到下标 end 的子数组和,特别要注意边界情况。

4.2 优化区间和查询的时间复杂度

def prefix_sum(nums):
    n = len(nums)
    prefix = [0] * (n + 1)
    
    for i in range(1, n + 1):
        prefix[i] = prefix[i - 1] + nums[i - 1]
    
    return prefix

def range_sum(prefix, start, end):
    return prefix[end + 1] - prefix[start]

def optimize_range_sum(prefix, start, end):
    return range_sum(prefix, start, end) if start == 0 else range_sum(prefix, start, end) - prefix[start]

在优化区间和查询的时间复杂度时,我们可以直接利用已经计算好的前缀和数组 prefix,通过 prefix[end + 1] - prefix[start] 可以得到从下标 start 到下标 end 的区间和。如果起始下标 start 不为0,我们可以通过 range_sum(prefix, start, end) - prefix[start] 计算区间和,避免重复计算前缀和。

4.3 前缀和数组的差分运算

def difference(nums):
    n = len(nums)
    dif = [0] * n
```python
def difference(nums):
    n = len(nums)
    dif = [0] * n
    dif[0] = nums[0]
    
    for i in range(1, n):
        dif[i] = nums[i] - nums[i - 1]
    
    return dif

def update(dif, start, end, value):
    dif[start] += value
    if end + 1 < len(dif):
        dif[end + 1] -= value

def recover(nums, dif):
    n = len(nums)
    nums[0] = dif[0]
    
    for i in range(1, n):
        nums[i] = dif[i] + nums[i - 1]
    
    return nums

 

通过差分运算,我们可以将原始数组转化为差分数组 dif。差分数组的特点是,差分数组中的值表示原始数组中相邻元素的差值。通过 dif[i] = nums[i] - nums[i - 1],可以得到差分数组。在进行数组元素的更新时,我们只需要更新差分数组中的相应位置,而不需要修改原始数组。通过 update 函数可以更新差分数组的指定范围内的值。最后,通过 recover 函数可以根据差分数组恢复原始数组的值。

5.1 问题描述

假设给定一个整数数组 nums,我们需要找到该数组中连续子数组的最大和。

5.2 基本解法

def max_subarray_sum(nums):
    n = len(nums)
    max_sum = float('-inf')
    
    for i in range(n):
        current_sum = 0
        for j in range(i, n):
            current_sum += nums[j]
            max_sum = max(max_sum, current_sum)
    
    return max_sum

基本解法是使用双重循环来枚举所有可能的连续子数组,并计算它们的和。在计算过程中,记录最大的和,最后返回最大和。

5.3 利用前缀和算法的优化解法

def max_subarray_sum(nums):
    n = len(nums)
    prefix = [0] * (n + 1)
    max_sum = float('-inf')
    
    for i in range(1, n + 1):
        prefix[i] = prefix[i - 1] + nums[i - 1]
    
    for i in range(n):
        for j in range(i, n):
            current_sum = prefix[j + 1] - prefix[i]
            max_sum = max(max_sum, current_sum)
    
    return max_sum

优化解法利用了前缀和算法来减少计算子数组和的时间复杂度。首先,通过计算前缀和数组 prefix,可以在常数时间内得到任意区间的和。然后,使用双重循环来枚举所有可能的连续子数组,但是在计算过程中,通过前缀和数组直接计算子数组的和,而不需要每次都重新计算。最后返回最大和。

总结

6.1 前缀和算法的优点

  • 前缀和算法能够高效地计算数组或序列中某个区间的和,大大减少了重复计算的时间复杂度。
  • 前缀和算法适用于需要频繁查询区间和或数组元素的更新和查询的场景。
  • 前缀和算法可以通过差分运算来进一步优化,减少空间复杂度。

6.2 注意事项和适用范围

  • 在使用前缀和算法时,需要注意边界情况和数组下标的处理,确保计算的正确性。
  • 前缀和算法适用于静态数组,即数组元素在查询和更新操作之间不会发生改变的情况。
  • 如果数组元素会发生频繁的更新操作,需要使用差分运算来处理,以避免重复计算前缀和。

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

刘知远LLM——Transformer与预训练模型

文章目录 注意力机制原理介绍注意力机制的各种变式注意力机制的特点 Transformer结构概述Transformer整体结构 输入层byte pair encodingpositional encoding Transformer BlockEncoder BlockMulti-Head Attention Decoder Block其他tricks总结 预训练语言模型语言建模概述预训…

DP读书:《半导体物理学(第八版)》(一)绪论 3min速通

DP读书&#xff1a;《半导体物理学&#xff08;第八版&#xff09;》刘恩科 3min速通半导体物理之绪论 DP读书&#xff1a;《半导体物理学&#xff08;第八版&#xff09;》刘恩科绪论第一章 半导体中的电子状态1.1 半导体的晶格结构和结合性质1.1.1 金刚石型结构和共价键1.1.2…

详解三种网络适配器:HBA、NIC 和 CNA

目录 前言&#xff1a; 一、主机总线适配器 (HBA) HBA的特点 二、网络接口卡 (NIC) NIC的特点 三、并发网络适配器 (CNA) CNA的特点 四、HBA、NIC 与 CNA的区别 五、结论 前言&#xff1a; 网络中的主机总线适配器 (HBA)、网络接口卡 (NIC) 和并发网络适配器 (CNA) 是…

视频号视频下载教程:如何把微信视频号的视频下载下来

视频号下载相信不少人都多少有一些了解&#xff0c;但今天我们就来细说一下关于视频号视频下载的相关疑问&#xff0c;以及大家经常会问到底如何把微信视频号的视频下载下来&#xff1f; 视频号视频下载教程 视频号链接提取器详细使用指南&#xff0c;教你轻松下载号视频&…

关于 cocos creator 如何打包抖音字节小游戏步骤一

1、cocos creator打开引擎&#xff0c;在顶部选择构建之后&#xff0c;在选择点击构建(ps:具体看项目组的大小&#xff0c;如果是一个简单的不多资源一般不到一分钟&#xff0c;如果项目很大&#xff0c;就至少半个小时以上)&#xff0c;之后 成功构建之后如下所示&#xff1a;…

欢迎免费申报讯方技术HarmonyOS人才训练营!

在今年1月备受瞩目的鸿蒙生态千帆启航仪式上&#xff0c;华为宣布&#xff1a;HarmonyOS NEXT星河预览版正式面向开发者开放申请&#xff0c;意味着鸿蒙将建立更广泛的生态系统&#xff0c;迎来更多的应用和软硬件产品&#xff0c;加速自我技术迭代&#xff0c;同时推动华为全场…

python 进程笔记二(通讯) (概念+示例代码)

1、为什么要掌握进程间通信 Python代码效率由于受制于GIL全局锁限制&#xff0c;多线程不能利用多核CPU来加速&#xff0c;而多进程方式却可以绕过GIL限制, 发挥多CPU加速的优势&#xff0c;达到提高程序的性能的目的。 然而进程间通信却是不得不考虑的问题。 进程不同于线程&a…

投资生涯的核心密码:构建交易逻辑体系

首先&#xff0c;我们需要明确一点&#xff0c;交易中究竟有没有确定性&#xff1f; 确定性是指在某一种形式、或有若干条件时&#xff0c;价格必然会上涨或下跌&#xff0c;也可以决定上涨或下跌的程度。 我认为&#xff0c;没有。迄今为止还没有一个理论能发现即使确定的东西…

金融知识分享系列之:五日线

金融知识分享系列之&#xff1a;五日线 一、股票均线二、五日线三、五日线加量能三、五日线案例四、五日线案例五、五日线案例六、五日线案例七、五日线案例八、五日线案例 一、股票均线 股票均线是一种用于平滑股票价格的指标。它是根据一段时间内的股票价格计算得出的平均值…

PureFlash v1.9.1特性介绍

PureFlashv1.9.1版本特性主要有3个&#xff1a; 1. 支持RDMA网络 使用RDMA协议可以大大减少对CPU的消耗&#xff0c;性能提升30%以上。 PureFlash的网络配置分为存储节点间网络&#xff08;存储后端网&#xff09;和客户端网络&#xff08;前端网&#xff09;。都支持使用RD…

C++:STL(标准模板库)

STL&#xff1a;主要是一些“容器”的集合&#xff1b;“容器”有&#xff1a;vector(数组)、list(双向链表)、deque(双向队列)、set(集合)、map(图&#xff1a;内部结构红黑树) STL也是算法和其他一些组件的集合&#xff0c;是泛型编程的一个经典范例。 STL的目的是标准化组…

数据分析-Pandas数据如何图示规律

数据分析-Pandas数据如何图示规律 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&…

一文读懂!ERP是什么?ERP和进销存有哪些区别?

ERP是什么&#xff1f;ERP和进销存有哪些区别&#xff1f; ERP和进销存可不止是叫法上的区别&#xff0c;这其中的门道还大着呢&#xff0c;今天就来跟大家详细讲解一下这些问题&#xff01;全文字数4000&#xff0c;干货满满&#xff0c;建议收藏&#xff01; 本文你将了解&…

无人驾驶-室内外循迹运行

1. 前言 好多初创公司公布出来的视频明显都是循迹的效果&#xff0c;不是说循迹不好&#xff0c;相反可以证明&#xff0c;循迹是自动技术开始的第一步。 自动驾驶循迹&#xff1a;一种能够自动按照给定的路线&#xff08;通常是采用不同颜色或者其他信号标记来引导&#xff…

✅技术社区项目—JWT身份验证

通用的JWT鉴权方案 JWT鉴权流程 基本流程分三步: ● 用户登录成功之后&#xff0c;后端将生成的jwt返回给前端&#xff0c;然后前端将其保存在本地缓存; ● 之后前端与后端的交互时&#xff0c;都将iwt放在请求头中&#xff0c;比如可以将其放在Http的身份认证的请求头 Author…

跨境外贸自动评论脚本开发常用代码!

随着跨境电商的兴起&#xff0c;自动化评论成为了提升销售和客户满意度的重要工具&#xff0c;通过编写自动评论脚本&#xff0c;商家可以快速地在各个平台留下正面评价&#xff0c;提高产品的曝光率和信誉度。 本文将介绍跨境外贸自动评论脚本开发的一些常用代码&#xff0c;…

STM32控制数码管从0显示到99

首先 先画电路图吧&#xff01;打开proteus&#xff0c;导入相关器件&#xff0c;绘制电路图。如下&#xff1a;&#xff08;记得要保存啊&#xff01;发现模拟一遍程序就自动退出了&#xff0c;有bug&#xff0c;我是解决不了&#xff0c;所以就是要及时保存&#xff0c;自己重…

远程访问Mysql数据库(最新有效)

在我们日常的开发中&#xff0c;我们的Mysql数据库一般都是不可以直接远程访问的&#xff0c;但有时候在特定的场景下&#xff0c;也想要远程访问&#xff0c;那要怎么配置呢&#xff1f; 其实要配置远程访问很简单&#xff0c;只需要做如下配置&#xff1a; 1.查看当前的用户…

代码随想录算法训练营day26

题目&#xff1a;39_组合总数&#xff08;没看题解&#xff09; 给定一个无重复元素的数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的数字可以无限制重复被选取。 说明&#xff1a; 所有数字&…

Yolov8有效涨点:YOLOv8-AM,添加多种注意力模块提高检测精度,含代码,超详细

前言 2023 年&#xff0c;Ultralytics 推出了最新版本的 YOLO 模型。注意力机制是提高模型性能最热门的方法之一。 本次介绍的是YOLOv8-AM&#xff0c;它将注意力机制融入到原始的YOLOv8架构中。具体来说&#xff0c;我们分别采用四个注意力模块&#xff1a;卷积块注意力模块…