当前位置: 首页 > news >正文

【算法笔记】前缀和算法原理深度剖析(超全详细版)

【算法笔记】前缀和算法原理深度剖析(超全详细版)

🔥个人主页大白的编程日记

🔥专栏算法笔记


文章目录

  • 【算法笔记】前缀和算法原理深度剖析(超全详细版)
    • 前言
    • 一.一维前缀和
      • 1.1题目
      • 1.2算法原理解析
      • 1.3代码实现
    • 二.二维前缀和
      • 2.1题目
      • 2.2算法原理解析
      • 2.3下标映射
      • 2.4初始化问题
      • 2.5代码实现
    • 三.寻找数组的中心下标
      • 3.1题目
      • 3.2思路分析
      • 3.3代码实现
    • 四.除自身以外数组的乘积
      • 4.1题目
      • 4.2思路分析
      • 4.3总结
      • 4.4代码实现
    • 五.和为k的子数组
      • 5.1题目
      • 5.2思路分析
      • 5.3代码实现
    • 六.和可被k整除的子数组
      • 6.1题目
      • 6.4思路分析
      • 6.3代码实现
    • 七.连续数组
      • 7.1题目
      • 7.1思路分析
      • 7.3代码实现
    • 八.矩阵区域和
      • 8.1题目
      • 8.2思路分析
      • 8.3代码实现
    • 后言

前言

哈喽,各位小伙伴大家好!上期我们讲了二分算法。今天我们来讲前缀和的算法原理。话不多说,咱们进入正题!向大厂冲锋!

一.一维前缀和

1.1题目

  • 题目:【模板】前缀和

1.2算法原理解析

我们根据前缀和算法就可以快速求出区间和。

为了防止越界,我们要让前缀和数组下标从1开始。

1.3代码实现

#include <iostream>
#include<vector>
using namespace std;
int main() 
{int n,q;cin>>n>>q;vector<long long> dp(n+1);//多开一个节点防止越界int tmp=0;for(int i=1;i<=n;i++){cin>>dp[i];}for(int i=1;i<=n;i++){dp[i]+=dp[i-1];}int l,r;while(q--){cin>>l>>r;cout<<dp[r]-dp[l-1]<<endl;}
}
// 64 位输出请用 printf("%lld")

二.二维前缀和

2.1题目

  • 题目:二维前缀和

2.2算法原理解析

2.3下标映射

2.4初始化问题

如果用到两个前缀和区间求某区间的和
我们初始化的值并不重要。
在这里插入图片描述

  • 验证

2.5代码实现

#include <iostream>
#include<vector>
using namespace std;int main()
{int n, m, q;cin >> n >> m >> q;vector<vector<long long>> arr(n,vector<long long>(m));for (int i = 0; i <n; i++){for (int j = 0; 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][j - 1]+dp[i-1][j]-dp[i-1][j-1]+arr[i-1][j-1];}}while (q--){int x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;long long sum=0;sum=dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1];cout<<sum<<endl;}
}

三.寻找数组的中心下标

3.1题目

  • 题目:寻找数组的中心下标

3.2思路分析

这里我们借助前缀和数组和后缀和数组即可快速判断中心下标。

3.3代码实现

class Solution {
public:int pivotIndex(vector<int>& nums){int n=nums.size();vector<int> f(n),g(n);for(int i=1;i<n;i++)//前缀和数组{f[i]=nums[i-1]+f[i-1];}for(int i=n-2;i>=0;i--)//后缀和数组{g[i]=g[i+1]+nums[i+1];}for(int i=0;i<n;i++)//判断{if(f[i]==g[i]){return i;}}return -1;}
};

四.除自身以外数组的乘积

4.1题目

  • 题目:除自身以外数组的乘积

4.2思路分析

4.3总结

4.4代码实现

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n=nums.size();vector<int> f(n),g(n),ret(n);f[0]=g[n-1]=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];}for(int i=0;i<n;i++){ret[i]=f[i]*g[i];}return ret;}
};

五.和为k的子数组

5.1题目

  • 题目:和为k的子数组

5.2思路分析

5.3代码实现

class Solution {
public:int subarraySum(vector<int>& nums, int k) {unordered_map<int,int> hash;hash[0]=1;//整个区间和为kint sum=0,ret=0;for(auto e:nums){sum+=e;//计算前缀和if(hash.count(sum-k))//统计和为sum-k区间个数{ret+=hash[sum-k];}hash[sum]++;//填入前缀和信息}return ret;}
};

六.和可被k整除的子数组

6.1题目

  • 题目:和可被k整除的子数组

6.4思路分析

6.3代码实现

class Solution {
public:int subarraysDivByK(vector<int>& nums, int k) {unordered_map<int,int> hash;hash[0]=1;//整个区间和为kint sum=0,ret=0;for(auto e:nums){sum+=e;//计算前缀和if(hash.count((sum%k+k)%k))//统计和为被k整除区间个数负数修正{ret+=hash[(sum%k+k)%k];}hash[(sum%k+k)%k]++;//填入前缀和%k信息}//(a-b)%p==a%p==b%p同余定理return ret;}
};

七.连续数组

7.1题目

  • 题目:连续数组

7.1思路分析

7.3代码实现

class Solution {
public:int findMaxLength(vector<int>& nums){unordered_map<int,int> hash;hash[0]=-1;int sum=0,len=0;for(int i=0;i<nums.size();i++){sum+=(nums[i]==0?-1:1);//0就变成-1;if(hash.count(sum-0)){len=max(len,i-hash[sum]);//更新长度}else//相同的前缀和不更新{hash[sum]=i;//更新哈希表前缀和信息}}return len;}
};

八.矩阵区域和

8.1题目

  • 题目:矩阵区域和

8.2思路分析

8.3代码实现

class Solution {
public:vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k){int m=mat.size(),n=mat[0].size();vector<vector<int>> arr(m+1,vector<int>(n+1));for(int i=1;i<m+1;i++)//处理前缀和数组{for(int j=1;j<n+1;j++){arr[i][j]=arr[i][j-1]+arr[i-1][j]-arr[i-1][j-1]+mat[i-1][j-1];}}vector<vector<int>> arr1(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 x2=min(m-1,i+k)+1;int y1=max(0,j-k)+1;int y2=min(n-1,j+k)+1;//计算下标 +1映射dp数组arr1[i][j]=arr[x2][y2]-arr[x2][y1-1]-arr[x1-1][y2]+arr[x1-1][y1-1];}}return arr1;}
};

后言

这就是前缀和算法原理的深度剖析。大家自己好好消化理解。今天 就分享到这,感谢各位大耐心垂阅!咱们下期见!拜拜~

http://www.lryc.cn/news/466930.html

相关文章:

  • linux之网络子系统- 地址解析协议arp 源码分析和邻居通用框架
  • 经典动态规划问题:含手续费的股票买卖【从 O(n) 到 O(1) 的优化解析】
  • Python画笔案例-088 绘制 滚动的汉字
  • Redis 5.0 安装配置(Windows)
  • 金融行业:办公安全防护专属攻略
  • python如何基于numpy pandas完成复杂的数据分析操作?
  • Linux中定时任务调度工具——crontab
  • 思维+差分,CF 1884C - Medium Design
  • 简单介绍冯诺依曼体系
  • kernel32.dll下载地址:如何安全地恢复系统文件
  • 【高等数学】多元微分学 (一)
  • Python爬取京东商品信息,详细讲解,手把手教学(附源码)
  • 大家有没有了解过TLKS-PLGS这款接地电阻在线监测装置?它在电力系统中能发挥什么作用呢?
  • Shell中的函数
  • 通过IP地址或者主机名添加打印机20241023
  • 基于SpringBoot+Vue智慧养老关爱系统【提供源码+答辩PPT+参考文档+项目部署】
  • 新手教学系列——利用短效代理快速搭建代理池
  • 实体与DTO如何转换
  • Docker 安装Postgres和PostGIS,并制作镜像
  • ES6:let和const命令解读以及变量的解构赋值
  • java-collection集合整理0.9.4
  • ParallelsDesktop20最新版本虚拟机 一键切换系统 游戏娱乐两不误
  • 现代C语言:C23标准重大更新
  • Maven进阶——坐标、依赖、仓库
  • Android中的内存泄漏及其检测方式
  • 【雷电模拟器命令合集操作大全】官方文档整理贴
  • redis的配置文件解析
  • Python中的元组和列表
  • 【AI战略思考7】粮草筹集完毕和我的朋友分类
  • 科大讯飞AI开发者大赛颁奖典礼,万码优才荣获前三甲!