前缀和算法:算法秘籍下的数据预言家

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

文章目录

目录

文章目录

前言

一. 前缀和算法的介绍

二、前缀和例题

2.1 【模版】前缀和

2.2 【模板】二维前缀和

 2.3 寻找数组的中间下标

 2.4 除自身以外数组的乘积

 2.5 和为k的子数组

2.6 和可被k整除的子数组

 2.7 连续数组

 2.8 矩阵区域和

总结


前言

本篇详细介绍了前缀和算法的使用,让使用者了解前缀和,而不是仅仅停留在表面, 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!


一. 前缀和算法的介绍

前缀和算法是一种用空间换时间的算法,他常常用于解决某些题目或者作为某些高级算法的组成部分。

例如:让你求某个矩阵(一维)的子矩阵的最大值,如果使用暴力解法它的时间复杂度将会是O(n^2) ,但如果使用该算法就可以使其时间复杂度降低一个维度也就是O(N).

前缀和 是从 nums 数组中的第 0 位置开始累加,到第 𝑖位置的累加结果,我们常把这个结果保存到数组 Sum 中,记为 Sum[i]。 

前缀和算法的本质是一个简单动态规划

 接下来我们使用一些例题来介绍一下

二、前缀和例题

2.1 【模版】前缀和

牛客网—【模版】前缀和

 

#include <iostream>
#include<vector>
using namespace std;

int main() {
    //1.读入数据
    int n ,q;
    cin>>n>>q;
    vector<int> arr(n+1);
    for(int i = 1;i<=n;i++) cin>>arr[i];

    //2. 预处理出来个前缀和数组
    vector<long long> dp(n+1); //防止溢出
    for(int i = 1;i<=n;i++) dp[i] = dp[i-1]+arr[i];

    //3.使用前缀和数组
    int l = 0, r = 0;
    while(q--)
    {
        cin>>l>>r;
        cout<<dp[r]-dp[l-1]<<endl;
    }
    return 0;

}

2.2 【模板】二维前缀和

牛客网—【模版】二维前缀和

 

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n,m,q;
    cin>>n>>m>>q;
    vector<vector<int>> arr(n+1,vector<int>(m+1));
    for(int i = 1;i<=n;i++)
    {
        for(int j = 1;j<=m;j++)
        {
            cin>>arr[i][j];
        }
    }

    vector<vector<long long>> dp(n+1,vector<long long>(m+1));
    for(int i = 1;i<=n;i++)
    {
        for(int j = 1;j<=m;j++)
        {
            dp[i][j] = dp[i-1][j] + dp[i][j-1] + arr[i][j] - dp[i-1][j-1];
        }
    }
    int x1 = 0,y1 = 0,x2 = 0 ,y2 = 0;
    while(q--)
    {
        cin>>x1>>y1>>x2>>y2;
        cout<<dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1]<<endl;
    }
    return 0;
}

 2.3 寻找数组的中间下标

724. 寻找数组的中心下标 - 力扣(LeetCode) 

 

class Solution {
public:
    int pivotIndex(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n), g(n);

        //1. 预处理前缀和数组和后缀和数组
        for(int i = 1;i<n;i++)
            f[i] = f[i-1] + nums[i-1];
        for(int i = n-2;i>=0;i--)
            g[i] = g[i+1] + nums[i+1];
        //2. 使用
        for(int i = 0;i<n;i++)
            if(f[i] == g[i]) 
                return i;

        return -1;

    }
};

 2.4 除自身以外数组的乘积

238. 除自身以外数组的乘积 - 力扣(LeetCode) 

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        //细节处理
        vector<int> f(n,1), g(n,1);
        //前缀和和后缀和
        for(int i = 1;i<n;i++)
            f[i] = f[i-1]*nums[i-1];
        for(int i = n-2;i>=0;i--)
            g[i] = g[i+1]*nums[i+1];
        //使用
        vector<int> ret(n);
        for(int i = 0;i<n;i++)
            ret[i] = f[i] * g[i];

        return ret;
    }
};

 2.5 和为k的子数组

560. 和为 K 的子数组 - 力扣(LeetCode)

 

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int,int> hash; //统计前缀和出现的次数
        hash[0] = 1;

        int sum = 0, ret = 0;
        for(auto&x : nums)
        {
            sum+=x; //计算当前位置的前缀和
            if(hash.count(sum-k)) ret+=hash[sum-k]; //统计个数
            hash[sum]++;
        }
        return ret;
    }
};

2.6 和可被k整除的子数组

974. 和可被 K 整除的子数组 - 力扣(LeetCode) 

 

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int,int> hash;
        hash[0 % k] = 1; //0 这个数的余数

        int sum = 0, ret = 0;
        for(auto& x : nums)
        {
            sum+=x; //算出当前位置的前缀和
            if(hash.count((sum%k+k)%k)) ret+=hash[(sum%k+k)%k]; //修正后的余数+统计结果
            hash[(sum%k+k)%k]++;
        }
        return ret;
    }
};

 2.7 连续数组

525. 连续数组 - 力扣(LeetCode) 

 

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int,int> hash;
        hash[0] = -1; //默认有一个前缀和为0的情况

        int sum = 0, ret = 0;
        for(int i = 0;i<nums.size();i++)
        {
            sum+=nums[i] == 0 ? -1 : 1; //计算当前位置的前缀和
            if(hash.count(sum)) ret = max(ret,i - hash[sum]);
            else hash[sum] = i;
        }
        return ret;

    }
};

 2.8 矩阵区域和

1314. 矩阵区域和 - 力扣(LeetCode)

 

class Solution {
public:
    vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
        int m = mat.size(), n = mat[0].size();
        vector<vector<int>> dp(m+1,vector<int>(n+1));
        for(int i = 1;i<=m;i++)
            for(int j = 1;j<=n;j++)
                dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + mat[i-1][j-1];

        vector<vector<int>> answer(m,vector<int>(n));
        for(int i = 0;i<m;i++)
            for(int j = 0;j<n;j++)
            {
                int x1 = max(0,i-k)+1;
                int y1 = max(0,j-k)+1;
                int x2 = min(m-1,i+k)+1;
                int y2 = min(n-1,j+k)+1;
                answer[i][j] = dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1];
            }
        return answer;

    }
};

总结

✨✨✨各位读友,本篇分享到内容是否更好的让你理解前缀和算法,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!

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

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

相关文章

数据资产管理实践白皮书4.0

数据资产管理实践白皮书4.0 在数字经济时代&#xff0c;数据已成为企业的重要资产。如何有效管理和利用这些数据&#xff0c;是企业在竞争中脱颖而出的关键。《数据资产管理实践白皮书4.0》为企业提供了一套系统的数据资产管理方法。本文将基于这本白皮书的内容&#xff0c;探…

JVM学习-JVM运行时参数

JVM参数选项 标准参数选项 特点 稳定&#xff0c;后续版本不会变化以【-】开头 各种选项 运行java或者java -help可以看到所有的标准选项 补充内容 -server&#xff1a;64位机器上只支持Server模式的JVM&#xff0c;适用于需要大内存的应用程序&#xff0c;默认用并行垃圾回…

高性能8位单片机 CA51M151,1T 8051内核 / 内置12位ADC / 16 位PWM / 支持触摸 / 8K MTP

CA51M151 系列芯片是基于 1T 8051 内核的 8 位微控制器&#xff0c;不仅保留了传统 8051 芯片的基本特性&#xff0c;通常情况下运行速度比传统的 8051 芯片快 10 倍&#xff0c;性能更加优越。芯片内置 8 KB MTP 程序存储器&#xff0c;256Byte 内部RAM&#xff0c;512Byte 外…

【日常记录】【node】从零开发一个node命令行工具

1、命令行工具 命令行工具&#xff08;Cmmand Line Interface&#xff09;简称cli&#xff0c;顾名思义就是在命令行终端中使用的工具。我们常用的 git 、npm、vim 等都是 cli 工具&#xff0c;比如我们可以通过 git clone 等命令简单把远程代码复制到本地。 再比如&#xff1a…

小程序 UI 风格,构建美妙视觉

小程序 UI 风格&#xff0c;构建美妙视觉

Prometheus写入influxDB:中间件remote_storage_adapter

Prometheus写入influxDB&#xff1a;中间件remote_storage_adapter prometheus默认采用的是本地磁盘做数据存储&#xff0c;本地存储的优势就是运维简单但是缺点就是无法海量的metrics持久化和数据存在丢失的风险,数据写入可能造成wal文件损坏导致采集数据无法再写入的问题。 …

使用Zed 实现测距

目录 1. 导入相关库 2. 相机初始化设置 3. 获取中心点深度数据 4. 计算中心点深度值 5. 完整代码 此代码基于官方代码基础上进行改写,主要是获取zed相机深度画面中心点的深度值,为yolo测距打基础。 Zed相机是由Stereolabs公司开发的一种先进的立体视觉相机。这种相机专…

openstack删除实例卡死在正在删除中

删除实例 问题描述解决办法 实验环境&#xff1b;服务器&#xff0c;openstackY版 问题描述 openstack在删除实例时一直显示正在删除中 解决办法 进入数据库修改实例状态&#xff0c;修改为错误&#xff0c;然后重新删除 首先查看对应实例id 进入数据库修改 rootcompute:~…

wx群发机器人.使用指南.

1.打开权限 1.打开下方Dock中 系统偏好设置 2.打开 安全性与隐私 3.打开 辅助功能 4.添加 终端 2.使用指南 1.下载 通讯录-联系人/群聊 1.先打开微信mac版,再打开群发机器人 2.点击下载 3.下载过程中,请不要操作键盘,鼠标 4.中途需停止可将鼠标放置左上角. 5.下载完成后文件…

vivado HW_TARGET

HW_目标 描述 硬件目标hw_target是包含一个或多个JTAG链的系统板 Xilinx FPGA设备&#xff0c;您可以使用比特流文件进行编程&#xff0c;或用于调试您的设计。 系统板上的硬件目标与Vivado Design Suite之间的连接 由硬件服务器对象hw_server管理。 使用open_hw_target命令打开…

Python深度学习基于Tensorflow(16)基于Transformer的对话实例

文章目录 基础数据清洗数据生成词汇表定义分词器并制作数据集构建Transformer模型并训练模型推理 Tensorflow 的核心就是注意力机制&#xff0c;在之前详细的介绍过&#xff0c;具体可以看这个&#xff1a;Python深度学习基于Tensorflow&#xff08;9&#xff09;注意力机制_te…

Python 深度学习和机器学习的模型评估库之torchmetrics使用详解

概要 在深度学习和机器学习项目中,模型评估是一个至关重要的环节。为了准确地评估模型的性能,开发者通常需要计算各种指标(metrics),如准确率、精确率、召回率、F1 分数等。torchmetrics 是一个用于 PyTorch 的开源库,提供了一组方便且高效的评估指标计算工具。本文将详…

GIS之arcgis系列10:arcpy实现批量掩膜提取

按掩膜提取 (Spatial Analyst) 提取掩膜所定义区域内的相应栅格像元。 OutRas ExtractByMask(InRas1, InMsk1, "INSIDE") 使用情况 输入栅格中的其他属性&#xff08;若有的话&#xff09;将按照原样添加到输出栅格属性表。 根据所记录的属性&#xff0c;某些属性…

【Java并发编程之美 | 第一篇】并发编程线程基础

文章目录 1.并发编程线程基础1.1什么是线程和进程&#xff1f;1.2线程创建与运行1.2.1继承Thread类1.2.2实现Runnable接口1.2.3实现Callable接口&#xff08;与线程池搭配使用&#xff09;1.2.4小结 1.3线程常用方法1.3.1线程等待与通知1.3.2线程睡眠1.3.3让出CPU执行权1.3.4线…

EVS9329-ES驱动器EVS9329ES可议价

EVS9329-ES驱动器EVS9329ES可议价 EVS9329-ES驱动器EVS9329ES可议价 EVS9329-ES驱动器EVS9329ES可议价 EVS9329-ES驱动器EVS9329ES可议价 EVS9329-ES驱动器EVS9329ES可议价 EVS9329-ES步进电机按结构分类&#xff1a;步进电动机也叫脉冲电机&#xff0c;包括反应式步进电动…

Unity射击游戏开发教程:(27)创建带有百分比的状态栏

创建带有弹药数和推进器百分比的状态栏 在本文中,我将介绍如何创建带有分数和百分比文本的常规状态栏。 由于 Ammo Bar 将成为 UI 的一部分,因此我们需要向 Canvas 添加一个空的 GameObject 并将其重命名为 AmmoBar。我们需要一个文本和两个图像对象,它们是 AmmoBar 的父级。…

13- 函数的定义与使用+形参实参区分

13- 函数的定义与使用形参实参区分 文章目录 13- 函数的定义与使用形参实参区分一、函数的定义与使用1.1 函数的结构1. 函数头2. 函数体 1.2 示例代码例子 1&#xff1a;无参数和无返回值的函数例子 2&#xff1a;带参数和返回值的函数 1.3 函数的基本语法1.4 函数的使用示例例…

多点液位传感器如何实现连续液位检测

如今&#xff0c;随着液位传感器的不断发展与演进&#xff0c;多点液位传感器也应用而生&#xff0c;可以实现对液体在多个连续点位的精确检测与监控&#xff0c;在洗地机设备上&#xff0c;可以及时了解水量&#xff0c;避免水资源浪费等情况。 多点式光电液位传感器采用了先…

测试记录4:在windows wsl2上配置ubuntu20.04

1.下载ubuntu20.04 (1) 在microsoft store中下载ubuntu20.04 (2) 在powershell中检查ubuntu20.04 wsl --listwsl -l -v安装成功 2.安装界面 见测试记录3 3.安装必要的功能包 sudo apt install zip sudo apt install gedit4.安装ros2 wget http://fishros.com/install -O …

提升你的编程体验:自定义 PyCharm 背景图片

首先&#xff0c;打开 PyCharm 的设置菜单&#xff0c;点击菜单栏中的 File > Settings 来访问设置&#xff0c;也可以通过快捷键 CtrlAItS 打开设置。 然后点击Appearance & Behavior > Appearance。 找到Background image...左键双击进入。 Image:传入自己需要设置…