前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【数据结构与算法】常用算法 前缀和

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

作者头像
苏泽
发布于 2024-03-01 04:55:15
发布于 2024-03-01 04:55:15
29100
代码可运行
举报
运行总次数:0
代码可运行

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

  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]中。具体的计算方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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表示区间的结束位置,区间和可以通过前缀和数组计算得到:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sum[left, right] = prefixSum[right+1] - prefixSum[left]

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

3.1 子数组和的计算

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 区间和的查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def range_sum(prefix, start, end):
    return prefix[end + 1] - prefix[start]

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

3.3 数组元素的更新和查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 前缀和数组的空间优化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 优化区间和查询的时间复杂度

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 前缀和数组的差分运算

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 基本解法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 利用前缀和算法的优化解法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 注意事项和适用范围
  • 在使用前缀和算法时,需要注意边界情况和数组下标的处理,确保计算的正确性。
  • 前缀和算法适用于静态数组,即数组元素在查询和更新操作之间不会发生改变的情况。
  • 如果数组元素会发生频繁的更新操作,需要使用差分运算来处理,以避免重复计算前缀和。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【前缀和】算法思想,附两道道手撕题
在算法设计和优化中,前缀和算法是一种简单而强大的技术,它通过预处理数组数据来加速对数组子区间和的查询。
鳄鱼儿
2024/12/29
2200
【前缀和】算法思想,附两道道手撕题
前缀和数组(算法)
前缀和(Prefix Sum)是指数组中某个位置之前的所有元素的和。对于数组 arr,其前缀和数组 prefixSum 定义为:
猫咪-9527
2025/01/13
1440
前缀和数组(算法)
【优选算法篇】前缀和与哈希表的完美结合:掌握子数组问题的关键(下篇)
引言:通过上篇文章带大家简单了解“前缀和算法”,小试牛刀。接下来将让大家感受一下前缀和在解题的妙处。
熬夜学编程的小王
2024/12/24
1550
【优选算法篇】前缀和与哈希表的完美结合:掌握子数组问题的关键(下篇)
前缀和算法详解
和一维的前缀和数组类似,这里需要先预处理出来一个前缀和矩阵 dp[][],dp[i][j] 就表示从(1,1)到(i,j)这个矩阵中的所有元素的和
2的n次方
2024/10/15
1180
前缀和算法详解
【前缀和的力量:高效解决子数组和矩阵问题的秘笈】—— 蓝桥杯高频热点题型知识点
前缀和(Prefix Sum)是一种常用的算法技巧,用于快速计算数组中某一范围的元素之和。
用户11286421
2025/03/17
1340
【前缀和的力量:高效解决子数组和矩阵问题的秘笈】—— 蓝桥杯高频热点题型知识点
【数据结构和算法】最大连续1的个数 III
这是力扣的 1004 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。
绿毛龟
2024/01/19
2350
【数据结构和算法】最大连续1的个数 III
【数据结构与算法】前缀和
https://blog.csdn.net/hsy1603914691/article/details/147820677
风中的云彩
2025/05/22
610
【数据结构与算法】前缀和
【优选算法篇】解密前缀和:让数组求和变得如此高效(上篇)
前缀和算法是解决一类常见数组问题的高效方法。它的核心价值在于将多次重复计算的部分进行优化,使得对数组的多次区间求和操作能在常数时间内完成。它不仅可以大幅减少时间复杂度,还能够应用于各种问题,如数组求和、子数组的最大/最小和等。
熬夜学编程的小王
2024/12/24
2000
【优选算法篇】解密前缀和:让数组求和变得如此高效(上篇)
信奥赛-刷题笔记-前缀和篇-T2-P6568[NOI Online #3 提高组] 水壶0523
https://docs.qq.com/sheet/DSmJuVXR4RUNVWWhW?tab=BB08J2
IT从业者张某某
2025/05/23
820
信奥赛-刷题笔记-前缀和篇-T2-P6568[NOI Online #3 提高组] 水壶0523
【C++】前缀和算法专题
⽤ dp[i] 表⽰: [1, i] 区间内所有元素的和,那么 dp[i - 1] ⾥⾯存的就是 [1,i - 1] 区间内所有元素的和,那么:可得递推公式: dp[i] = dp[i - 1] +arr[i] ;
啊QQQQQ
2024/11/19
1070
【C++】前缀和算法专题
备战蓝桥杯————前缀和数组1
定义:前缀和数组(Prefix Sum Array)是一个数组,它存储了原数组(或序列)的连续子数组之和。对于一个给定的数组 nums,其前缀和数组 cumulativeSum 的第 i 个元素 cumulativeSum[i] 表示 nums 从第一个元素到第 i 个元素的累加和。
小小程序员
2024/02/29
1540
【数据结构和算法】删掉一个元素以后全为 1 的最长子数组
这是力扣的 1493 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。
绿毛龟
2024/01/19
1520
【数据结构和算法】删掉一个元素以后全为 1 的最长子数组
【算法专题】前缀和
题目:给定一个长度为n的数组 a1​, a2​, …an. 接下来有q次查询, 每次查询有两个参数l, r. 对于每个询问, 请输出 al + al + 1 + … + ar
YoungMLet
2024/03/01
1650
【算法专题】前缀和
论那些小而美的算法技巧:差分数组/前缀和
大家好,我是算法老司机 labuladong,本文给大家介绍一个小而美的算法技巧:差分数组。
labuladong
2021/09/23
2840
【C++例题/训练】:前缀和&&差分
前面我们已经通过 【算法/学习】前缀和&&差分-CSDN博客 学习了前缀和&&差分的效相关知识,现在我们开始进行相关题目的练习吧
IsLand1314
2024/10/15
1320
【C++例题/训练】:前缀和&&差分
深度解析算法之前缀和
这个题的话就是下面的样子,我们第一行输入 3 2的意思即是这个数组是3个元素大小的数组,2是接下来我们是需要输入两行数据下标的 然后第二行我们输入的n个整数表示的就是我们数组中的元素 然后后面的2行就是我们想计算数组中从哪里到哪里的和 这里的话我们是第一个数到第二个数的和,那么我们这里的就是3了
Undoom
2025/04/21
680
深度解析算法之前缀和
【优选算法】Prefix-Kage:前缀和的算法影(上)
🚩什么是前缀和算法? 前缀和算法是一种用于高效计算数组区间和的算法。对于一个给定的数组 nums,我们可以预先计算出它的前缀和数组 prefixSum ,其中 prefixSum[i] 表示 nums[0] 到 nums[i] 的元素之和
DARLING Zero two
2024/12/24
720
【优选算法】Prefix-Kage:前缀和的算法影(上)
拼多多算法题,是清华考研真题!
不仅是拼多多,该题还在诸如 神州信息 和 滴滴出行 这样的互联网大厂笔试中出现过:
宫水三叶的刷题日记
2023/12/13
4140
拼多多算法题,是清华考研真题!
【算法一周目】从时光的边缘看世界:前缀和揭示的算法真谛
给定一个长度为 n 的整数数组 arr 和 q 个查询,每个查询由两个整数 l 和 r 组成,表示区间 [l, r]。请计算出每个区间内所有元素的和。
HZzzzzLu
2024/12/31
950
【算法一周目】从时光的边缘看世界:前缀和揭示的算法真谛
我爱学算法之—— 前缀和(中)
遍历到i位置时,判断该位置是否是中心下标,也就是该位置左侧所有元素是否等于右侧所有元素。
星辰与你
2025/06/08
490
我爱学算法之—— 前缀和(中)
推荐阅读
相关推荐
【前缀和】算法思想,附两道道手撕题
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验