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

news2025/4/25 22:34:02

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

文章目录

目录

文章目录

前言

一. 前缀和算法的介绍

二、前缀和例题

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;

    }
};

总结

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

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

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

相关文章

如何将NextJs中的File docx保存到Prisma ORM

背景/引言 在现代 Web 开发中&#xff0c;Next.js 是一个备受欢迎的 React 框架&#xff0c;它具有许多优点&#xff0c;如&#xff1a; 服务器端渲染 (SSR)&#xff1a;Next.js 支持服务器端渲染&#xff0c;可以提高页面加载速度&#xff0c;改善 SEO&#xff0c;并提供更好…

【AI工具】jupyter notebook和jupyterlab对比和安装

简单说&#xff0c;jupyterlab是jupyter notebook的下一代。 选择安装一个即可。 一、这里是AI对比介绍 Jupyter Notebook和JupyterLab都是基于Jupyter内核的交互式计算环境&#xff0c;但它们在设计和功能上有一些关键的区别&#xff1a; 用户界面&#xff1a; Jupyter Not…

关于对pagination.js源代码进行修改且引入项目使用

实现效果 使用定时器对组件进行每秒请求&#xff0c;每过固定时间之后&#xff0c;进行下一页项目请求&#xff0c;进行到最后一页请求的时候返回第一页。 首先引入js插件 <script src"./js/pagination.js" type"text/javascript"></script>…

粉丝经济时代:微信订阅号如何助力中小企业增长

在数字化浪潮席卷全球的今天&#xff0c;微信订阅号凭借其独特的优势&#xff0c;成为了中小企业数字化出海的重要工具。作为NetFarmer&#xff0c;我们致力于帮助企业充分利用这一平台&#xff0c;推动业务发展和市场拓展。今天将深入探讨微信订阅号的概念、用途、使用方法、适…

若依修改浏览器标题logo

在线生成透明ICO图标——ICO图标制作https://www.ico51.cn/

使用ZIP包安装MySQL及配置教程

在本教程中&#xff0c;我们将指导您完成使用ZIP包安装MySQL的过程&#xff0c;并对配置文件进行必要的修改&#xff0c;以及解决可能遇到的问题。本示例以MySQL 5.7.44为例&#xff0c;但步骤同样适用于其他版本如MySQL 8.3.0等。请根据实际需要选择适合的版本下载&#xff1a…

【机器学习】神经网络与深度学习:探索智能计算的前沿

前沿 神经网络&#xff1a;模拟人类神经系统的计算模型 基本概念 神经网络&#xff0c;又称人工神经网络&#xff08;ANN, Artificial Neural Network&#xff09;&#xff0c;是一种模拟人类神经系统结构和功能的计算模型。它由大量神经元&#xff08;节点&#xff09;相互连…

报表生成中,左连接、内连接区别与应用

在报表生成中,最常用的连接类型包括:内连接(INNER JOIN)、左连接(LEFT JOIN)。以下是这些连接的简要介绍及其在报表中的应用场景: 左连接 左连接返回左表中的所有记录,以及右表中与左表匹配的记录。如果右表中没有匹配的记录,则右表中的字段值为NULL。 应用场景: …

汽车油耗NEDC与WLTP有什么区别?以及MATLAB/Simulink的汽车行驶工况仿真

最近的热点新闻非比亚迪的秦L莫属&#xff0c;其油耗达到2.9L/100km&#xff0c;但其标注为NEDC也引起了讨论&#xff0c; NEDC与WLTP的区别 NEDC的全称为“New European Driving Cycle”&#xff0c;即“新欧洲驾驶循环”。这种油耗测试标准起源于上世纪80年代&#xff0c;主…

Visual Studio Code远程linux计算云

一、前置条件 本机安装Visual Studio Code 打开Vscode时建议使用管理员权限打开&#xff0c;在这之前遇到了一些报错。 二、开始远程连接计算云 安装插件remote-ssh 2.点击远程资源管理器&#xff0c;之后在SSH这行的右侧&#xff0c;点击“”号&#xff0c;去新建远程 3.在窗…

Linux指令学习(4)

目录 0.普通用户和root用户之间的切换 1.head/tail指令 2.管道 3.date命令 4.三个查找相关的指令 5.文件过滤grep 6.打包和压缩 5.zip/unzip指令 0.普通用户和root用户之间的切换 &#xff08;1&#xff09;这个我们之前不是经常使用这个root用户吗&#xff0c;现在随着…

【安卓设备】通过adb批量安装apk

1、adb链接设备 H:\tv\apk>adb connect 127.0.0.1:21503 2、批量安装apk 如果地址不一致需要将 H:\tv\apk\ 改成自己的路径地址&#xff0c;同时注意该命令只能安装文件名为英文的不支持中文名称&#xff0c;如果有需要先更改文件名称。 H:\tv\apk>for %f in (H:\tv\a…

电商项目的性能测试流程,看完就懂!

今天给大家带来一套完整的性能测试实操流程&#xff0c;就以大家耳熟能详的电商项目来进行示例。现在就花个5分钟&#xff0c;认真看一下吧&#xff01; 一、核心业务梳理 做一个项目的性能测试&#xff0c;首先得梳理出哪些业务需要进行性能测试。这个过程有一个前提就是&…

openGauss学习笔记-300 openGauss AI特性-AI4DB数据库自治运维-DBMind的AI子功能-SQL Rewriter SQL语句改写

文章目录 openGauss学习笔记-300 openGauss AI特性-AI4DB数据库自治运维-DBMind的AI子功能-SQL Rewriter SQL语句改写300.1 概述300.2 使用指导300.2.1 前提条件300.2.2 使用方法示例300.3 获取帮助300.4 命令参考300.5 常见问题处理openGauss学习笔记-300 openGauss AI特性-AI…

【JS重点14】内置构造函数

一:Object构造函数 1 创建对象说明 Object是内置的构造函数&#xff0c;用于创建普通对象。 //通过构造函数方式创建普通对象 const user new Object({name:佩奇,age:18})相较于&#xff0c;利用字面量声明对象利用构造函数方式麻烦&#xff0c;因此推荐利用字面量方式声明…

OpenCV单词轮廓检测

OpenCV单词轮廓检测 0. 前言1. 策略分析2. 检测字符轮廓3. 检测单词轮廓相关链接 0. 前言 在根据文档图像执行单词转录时&#xff0c;通常第一步是识别图像中单词的位置。我们可以使用两种不同的方法识别图像中的单词&#xff1a; 使用 CRAFT、EAST 等深度学习技术使用基于 O…

【算法-力扣】72. 编辑距离(动态规划)

目录 一、题目描述 二、解题思路 三、参考答案 一、题目描述 编辑距离 给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作&#xff1a; 插入一个字符 删除一个字符 替换一个字符 示例 1&#…

win11电脑桌面倒计时提醒怎么设置?

在日常工作中&#xff0c;我们经常需要处理大量的工作任务&#xff0c;而且很多任务都有时间限制。如果将这些任务记录在桌面上&#xff0c;并设置倒计时提醒&#xff0c;无疑会大大提高我们的工作效率。想象一下&#xff0c;在繁忙的工作间隙&#xff0c;你只需一瞥桌面&#…

618火爆来袭,退换货花费多咋办?

姐妹们&#xff0c;一年一度的618就要来了&#xff0c;你准备好了吗&#xff0c;虽然咱们的钱包鼓鼓的&#xff0c;但是咱们的购物袋也要鼓鼓的呀&#xff0c;我们就是要多买&#xff0c;多买&#xff0c;多买&#xff0c;这样才能更显示出自己更爱自己了。 言归正传&#xff…

2024.6.14 刷题总结

2024.6.14 **每日一题** 2786.访问数组中的位置使分数最大&#xff0c;看到这题就想到动态规划的思路&#xff0c;遍历数组&#xff0c;每次选择移动该元素时能获得到的最大值&#xff0c;分别考虑最后一个的元素为奇数/偶数的最大值&#xff0c;用长度为2的数组来储存这两个值…