【基础算法】前缀和

embedded/2024/10/18 12:22:59/

1.【模板】前缀和

前缀和

思路:

板子题,思路前缀和数组记录 。

虽是板子,但以后切记不要死记模版。

主要要开long long,防溢出。

#include <iostream>
using namespace std;#include<vector>int main() 
{int n = 0, q = 0;cin >> n >> q;vector<int> arr(n);for(int i = 0; i < n; i++) cin >> arr[i];//填充前缀和数组vector<long long> dp(n + 1);for(int i = 1; i <= n; i++) dp[i] = dp[i - 1] + arr[i - 1];//q次查询while(q--){int l = 0, r = 0;cin >> l >> r;cout << dp[r] - dp[l - 1] << endl;}return 0;
}

 2.【模板】二维前缀和

二维前缀和

思路:

二维的模板题。

此图借助理解

 

#include <iostream>
using namespace std;#include<vector>int main() 
{int n = 0, m = 0, q = 0;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];//填充dp表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][j];while(q--){int x1 = 0, y1 = 0, x2 = 0, y2 = 0;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;    
}

3.寻找数组的中心下标 

寻找数组的中心下标

思路:

求解前缀和与后缀和

比较i位置的前缀和与后缀和是否相等 

class Solution {
public:int pivotIndex(vector<int>& nums) {int n = nums.size();//f[i]表示:[0, i - 1]内的所有数的和//g[i]表示:[i + 1, n - 1]内的所有数的和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];for(int i = 0; i < n; i++){if(f[i] == g[i]) return i;}return -1;}
};

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

除自身以外数组的乘积

思路:

跟3类似,只是f[i]与g[i]的状态发生了变化,变为了乘法。

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> ans(n);//填充dp表vector<int> f(n), g(n);//初始化f[0] = 1, 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++){ans[i] = f[i] * g[i];}return ans;}
};

5.和为k的子数组

和为k的子数组

 思路:

前缀和与哈希表结合,让我们求子数组和为k,即让我们求前缀和的sum - k出现的次数。

class Solution {
public:int subarraySum(vector<int>& nums, int k) {int sum = 0, ret = 0;unordered_map<int, int> hash; // 记录子数组和为k的个数// 细节问题 - 子数组为0时的数量默认为1hash[0] = 1;for(auto x : nums){sum += x;// 计算当前位置的前缀和if(hash.count(sum - k)) ret += hash[sum - k];//更新结果hash[sum]++;// 统计子数组和的次数}return ret;}
};

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

和可被k整除的子数组

思路:

与4类似,只是hash里面存的内容有所不同

同余定理:(sum - x) % p = 0 -> sum % p == x % p.

c++/java中的负数%正数的修正(a%b + b) % b

 

class Solution {
public:int subarraysDivByK(vector<int>& nums, int k) {unordered_map<int, int> hash;//记录前缀余数出现的次数//处理细节问题hash[0 % k] = 1;//0 - 代表余数为0出现的次数默认为1int sum = 0, ret = 0;for(auto x : nums){sum += x;// 当前位置的前缀和int r = (sum % k + k) % k;// 修正后的求当前位置的余数if(hash.count(r)) ret += hash[r];// 更新结果hash[r]++;}return ret;}
};

 7.连续数组

连续数组

思路:

与和为k的子数组类似

细节问题比较特殊

哈希表存放的是什么?

hash【0】应该存什么?

class Solution {
public:int findMaxLength(vector<int>& nums) {//把0都转化为-1,就可以用我们的前缀和求解了-> 实质就是求子数组为k时对应的子数组长度unordered_map<int, int> hash;// 存放的是sum的对应下标//处理细节问题hash[0] = -1;// hash表内存放的是下标,所以前缀和为0只能是-1int 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;}
};

 8.矩阵区域和

矩阵区域和

思路:

二维前缀和

细节:处理映射关系上如何处理?

class Solution {
public:vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {int m = mat.size(), n = mat[0].size();//创建dp表vector<vector<int>> dp(m + 1, vector<int>(n + 1));//填写dp表//注意dp表与mat矩阵的映射关系mat[i - 1][j - 1]还是mat[i][j]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>> ret(m, vector<int>(n));for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){//使dp数组下标映射和原数组对齐int x1 = max(0, i - k) + 1, y1 = max(0, j - k) + 1;int x2 = min(m - 1, i + k) + 1, y2 = min(n - 1, j + k) + 1;ret[i][j] = dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1];}return ret;}
};

 


http://www.ppmy.cn/embedded/23989.html

相关文章

MIS微调SAM模型实时交互UI界面

前言 SAM模型的基本介绍可见SAM&#xff08;Segment Anything Model&#xff09;大模型使用--point prompt_sam大模型-CSDN博客 针对Meta团队去年发布的SAM大模型在医学图像分割领域表现性能较差的情况&#xff0c;笔者收集了一些MIS领域的数据集对SAM的架构进行fine tune&am…

数据分析案例-全球表面温度数据可视化与统计分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Linux详解:进程等待

文章目录 进程等待等待的必要性进程等待的方法waitwaitpid获取子进程status阻塞等待 与 非阻塞等待 进程等待 等待的必要性 子进程退出&#xff0c;父进程不进行回收的话&#xff0c;就可能造成僵尸进程&#xff0c;进而造成内存泄露 如果进程进入了僵尸状态&#xff0c;kill…

Unity DOTS1.0 入门(7) BlobAsset 核心机制概述

BlobAsset 概述&#xff1a; Blob Asset是一种特殊的数据结构&#xff0c;用于存储不可变的、只读的、大量的数据。Blob是Binary Large Object的缩写&#xff0c;意为二进制大对象。Blob Asset的主要特点是它们是不可变的&#xff0c;并且可以在内存中任意移动&#xff0c;这…

ansible提示 python 报错的问题及解决

这个警告是提醒您当前的Ansible配置在目标主机上使用的是/usr/bin/python而不是建议的/usr/bin/python3&#xff0c;因为Ansible 2.9版本之前的某些版本默认使用早期的Python 2.x版本。然而&#xff0c;在将来的版本中&#xff0c;Ansible将会默认使用已发现的平台默认的 Pytho…

JS事件循环、宏任务与微任务

在JavaScript中&#xff0c;事件循环&#xff08;Event Loop&#xff09;是处理异步操作的核心机制。它负责执行代码&#xff0c;处理事件&#xff0c;并在适当的时候调度回调。为了更好地理解JavaScript的执行模型&#xff0c;我们需要深入探讨事件循环、宏任务&#xff08;Ma…

Rust检查一个Vec<String>是否包含一个特定的子字符串

在Rust中&#xff0c;你可以使用contains方法来检查一个Vec<&str>是否包含特定的字符串。但是&#xff0c;如果你想检查一个Vec是否包含一个特定的子字符串&#xff0c;你需要先将子字符串转换为String。 以下是一个示例代码&#xff0c;展示了如何检查一个Vec是否包…

《软件设计师教程:数据库系统基础知识大总结》

​ 个人主页&#xff1a;李仙桎 &#x1f525; 个人专栏: 《软件设计师》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ​ ⛺️前言&#xff1a;各位铁汁们好啊&#xff01;&#xff01;&#xff01;今天继续正式学习中级软件设计师考试相关的内容&#xff0c;后续不断更新…