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

news2024/12/27 17:28:41

 🎉🎉欢迎光临🎉🎉

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

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

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

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

努力的苏泽icon-default.png?t=N7T8http://suzee.blog.csdn.net

引言:


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

  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 注意事项和适用范围

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

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

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

相关文章

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

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

RabbitMQ开启MQTT协议支持

1&#xff09;RabbitMQ启用MQTT插件 rootmq:/# rabbitmq-plugins enable rabbitmq_mqtt Enabling plugins on node rabbitmq: rabbitmq_mqtt The following plugins have been configured:rabbitmq_managementrabbitmq_management_agentrabbitmq_mqttrabbitmq_web_dispatch Ap…

leet hot 100-6 三数之和

三数之和 原题链接思路代码 原题链接 leet hot 100-5 15. 三数之和 思路 从前往后定义第一个数字 first 开始遍历整个数组 然后要求 frist和上一个数字不重复否则就是重复组合 从frist往后遍历第二个数字 同样要求第二个数字不能重复 再定义第三个数字从后往前面数 三个数字…

【MySQL】表的约束 -- 详解

表中一定要有各种约束&#xff0c;通过约束让我们在未来插入数据库表中的数据是符合预期的。约束本质是通过技术手段倒逼程序员插入正确的数据&#xff0c;反过来站在 MySQL 的角度&#xff0c;凡是插入进来的数据都是符合数据约束的。约束的最终目标&#xff1a;保证数据的完整…

试一下newb,还是有错误呀

解题&#xff1a;原式&#xff1d; 2. 在递增的等比数列 ( a n ) (a_n) (an​)中&#xff0c;若 ( a 3 − a 1 5 2 ) (a_3 - a_1 \frac{5}{2}) (a3​−a1​25​), ( a 2 3 ) (a_2 3) (a2​3), 则公比 (q) A. ( 4 3 ) ( \frac{4}{3} ) (34​) B. ( 3 2 ) ( \frac{3}{2} …

蛇形矩阵1

题目描述 把数1&#xff0c;2&#xff0c;3&#xff0c;…&#xff0c;N*N按照“蛇形1”放入N*N的矩形中&#xff0c;输出结果。 下面是N10的蛇形1的图示 输入格式 第一行1个正整数&#xff1a;N&#xff0c;范围在[1,100]。 输出格式 N行&#xff0c;每行N个整数。 输入/…

GTSAM 中的鲁棒噪声模型与 M-估计 (GTSAM Robust Noise Model and M-Estimator)

Title: GTSAM 中的鲁棒噪声模型与 M-估计 (GTSAM Robust Noise Model and M-Estimator) 文章目录 前言I. 噪声模型II. 鲁棒回归 —— M 估计1. 线性回归2. 损失函数3. 加权最小二乘 III. 鲁棒噪声模型1. 鲁棒目标函数2. 非线性加权最小二乘3. 迭代重加权最小二乘法 V. 总结参考…

第 2 章 微信小程序的构成 (代码导读)断更,后续继续更新

2.1 小程序项目的基本结构 Hello World&#xff01;程序.mp4 文泉云盘 -- 图书二维码资源管理系统兆泰源二维码管理系统https://www.wqyunpan.com/resourceDetail.html?id284928&openIdoUgl9wdyNYHu9EcAe-GEwbQdZilY&qrcodeId242916&signc2lnbm1PUmNxSndPWGFOck…

rhel8配置bond遇到的问题汇总

操作环境信息 配置bond mode=4 两块网卡的配置信息 bond卡的配置信息(标红是后来加上的) 遇到的问题 rhel8 使用NetworkManage 管理网络,而不使用network,经常用到的命令是nmcli 拉起bond0后,因为没有获取到ip地址,每隔一段时间就会将网卡down掉,出现nic link is down …

代码随想录算法训练营第四三天 | 最后一块石头的重量 II、目标和、一和零

目录 最后一块石头的重量 II目标和一和零 LeetCode 1049. 最后一块石头的重量 II LeetCode 494. 目标和 LeetCode 474.一和零 最后一块石头的重量 II class Solution {// dp[j] 容量为j 的背包&#xff0c;最多可以背最大重量为dp[j]。// dp[j] Math.max(dp[j], dp[j - sto…

zabbix3.4.6 源码安装

Step1&#xff1a; 下载 https://www.zabbix.com/download 选中一下。download Zabbix Sources PackageReleaseDateRelease NotesZabbix ManualDownloadZabbix 3.4Server, Proxy, Agent, GUI3.4.615 January, 2018 Download step2 &#xff1a;拷贝在redhat 6.3_X86_86(192…

基于huggingface加载openai/clip-vit-large-patch14-336视觉模型demo

文章目录 引言一、模型加载二、huggingface梯度更新使用三、图像处理四、模型推理五、整体代码总结 引言 本文介绍如何使用huggingface加载视觉模型openai/clip-vit-large-patch14-336&#xff0c;我之所以记录此方法源于现有大模型基本采用huggingface库来加载视觉模型和大语…

【生成式AI】ChatGPT 原理解析(2/3)- 预训练 Pre-train

Hung-yi Lee 课件整理 预训练得到的模型我们叫自监督学习模型&#xff08;Self-supervised Learning&#xff09;&#xff0c;也叫基石模型&#xff08;foundation modle&#xff09;。 文章目录 机器是怎么学习的ChatGPT里面的监督学习GPT-2GPT-3和GPT-3.5GPTChatGPT支持多语言…

nginx(二)

nginx的验证模块 输入用户名和密码 第一步先下载httpd 这个安装包 第二步编辑子配置文件 然后去网页访问192.168.68.3/admin/ 连接之后&#xff0c;会出现404&#xff0c;404出现是因为没给网页写页面 如果要写页面&#xff0c;则在/opt/html&#xff0c;建立一个admin&#x…

算法沉淀——动态规划之路径问题(leetcode真题剖析)

算法沉淀——动态规划之路径问题 01.不同路径02.不同路径 II03.珠宝的最高价值04.下降路径最小和05.最小路径和06.地下城游戏 01.不同路径 题目链接&#xff1a;https://leetcode.cn/problems/unique-paths/ 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图…

探索C语言位段的秘密

位段 1. 什么是位段2. 位段的内存分配3. 位段的跨平台问题4. 位段的应用4. 使用位段的注意事项 1. 什么是位段 我们使用结构体实现位段&#xff0c;位段的声明和结构体是类似的&#xff0c;有两个不同&#xff1a; 位段的成员必须是int&#xff0c;unsigned int&#xff0c;或…

IO进程线程作业day7

信号灯集共享内存 自定义头文件 #ifndef SEM_H_ #define SEM_H_ //创建信号灯集, int creat_t(int number); //申请释放资源 int P(int semid,int semno); //申请释放资源 int V(int semid,int semno); //删除信号灯集 int del(int semid); #endif信号灯集函数集合 #include…

多维时序 | Matlab实现GRU-MATT门控循环单元融合多头注意力多变量时间序列预测模型

多维时序 | Matlab实现GRU-MATT门控循环单元融合多头注意力多变量时间序列预测模型 目录 多维时序 | Matlab实现GRU-MATT门控循环单元融合多头注意力多变量时间序列预测模型预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.多维时序 | Matlab实现GRU-MATT门控循环单元融…

wcf 简单实践 数据绑定 数据更新ui

1.概要 2.代码 2.1 xaml <Window x:Class"WpfApp3.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expr…

《数据治理简易速速上手小册》第2章 数据治理框架的建立(2024 最新版)

文章目录 2.1 确立数据治理目标2.1.1 基础知识2.1.2 重点案例&#xff1a;提升零售业数据质量2.1.3 拓展案例 1&#xff1a;银行的数据安全加强2.1.4 拓展案例 2&#xff1a;医疗机构的合规性数据报告 2.2 数据治理框架的关键要素2.2.1 基础知识2.2.2 重点案例&#xff1a;制药…