【C/C++算法】从浅到深学习--- 前缀和算法(图文兼备 + 源码详解)
绪论:冲击蓝桥杯一起加油!!
每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry”
绪论:
本章将使用八道题由浅到深的带你了解并基本掌握前缀和思想,以及前缀和的基本用法!
————————
早关注不迷路,话不多说安全带系好,发车啦(建议电脑观看)。
前缀和算法总结:
常规的前缀和分为两种(也是练习1、2):
-
一维前缀和:比较简单,在我们需要快速的算出某一数组中的数据时,可以想想是否能使用前缀和,它的使用条件:
- 一维数组
- 求数组中任意连续的值
- 对于满足上述条件后就能考虑使用前缀和数组
- 其中前缀和数组存储
dp[ i ]
的是:从1~ i
区域内的元素值之和 - 其中下标从1开始算,每次创建的数组大小为 n + 1 保证从 1 开始(从1开始是因为: 计算 dp[i] 需要使用 dp[i - 1],假设 i 不从1开始,若 i 为0,就会越界访问)
- 具体当我们拥有了一个前缀和数组dp后,使用前缀和数组算出结果,当要求
r ~ l
这段区间时它的计算方法就是:dp[ r ] - dp[ l -1 ]
-
二维前缀和:
-
条件类似:二维数组,当要求某一块区间的值时 可以考虑使用二维前缀和
-
该二维前缀和数组
dp[ i ][ j ]
中存储的是:从(0,0) ~ (i,j)
区域的所有元素值的和
-
使用:对于二维前缀和的使用稍微对比起来有点难度,一般来说需要使用到两个公式
- 计算出二维前缀和数组中的值的公式:dp[ i ][ j ] = dp[ i ][ j - 1] + dp[ i-1 ][ j ] + arr[ i ][ j ] - dp[ i - 1 ][ j - 1 ]
对于该公式,切记一定不要死记
通过下图右边图记忆:
理解:当我们我们要求的空间可以分为右边图形中的四块:A、B、C、D,其中假如我们从上往下,从左往右的去填写当前的dp数组时,本质上 A、B、C三个区域的值都是已经算好了的,而对于 D 来说他就是自身当前位置的值 arr[ i ][ j ],所以这样我们就能得出上面的公式:
A = dp[ i - 1][ j - 1 ]、B = dp[ i - 1][ j ]、C = dp[ i ][ j - 1 ]、D = arr[ i ][ j ]
- 使用二维前缀和公式快速算出任意两点
(x1,y1) ~ (x2,y2)
区域的公式:dp[ x2 ][ y2 ] - dp[ x1 - 1 ][ y2 ] - dp[ x2 ][ y1 - 1 ] - dp[ x2 ][ y1 - 1] + dp[ x1 - 1][ y1 - 1 ]
而对于这个公式来说同样,也是通过一张图进行记忆:
具体如下就过诉了,这里本质要求的就是 D 区域,如何通过 提前准备好的 二维前缀和数组 求出 D区域的值(同样还是记忆下面右图逻辑即可,必要时画个图)
-
-
其中前缀和只是个思想,它使用一个数组的形式提前存储一段区间的值,其中这个 区间的值的求法,可能并不一样
- 比如存储了
1 ~ i
区间的和、 - 存储了
1 ~ i
区间的乘积、 - 存储了
1 ~ i
区间的某个数的出现个数… - 再或者是一个后缀和(从后往前的记录其中的值)
- 比如存储了
- 始终记住前缀和可以用来求出某一段连续区域的值的思想,后面首先会通过两道简单的题(一维和二维前缀和练手),后面将会逐步递增难度(也就代表这个前缀和中存储的并不是 前缀的和)
- 过程中一般都是求某段连续区域中的某个值,对于感觉大脑不够想的时候一定要画图!通过简单的图示更方便的理解和写出公式
具体训练:
1. 一维前缀和【模板】
题目:
分析题目并提出,解决方法:
结合题目分析:
- 首行是 n :数组个数、q:查询次数
- 第二行是有n个元素的数组的值:…
- 后面有q行,它的值代表查找区间 [左 ~ 右]
- 那么然后输出查询结果
- 例如在下面 1 2 4 数组中查找(1,2)、(2,3)、(1,3) 区间的值,具体如下
暴力题解:简单的模拟,根据给q次给的left、right下标,并从该区间【left,right】遍历求和得出答案(O(n * q)的时间复杂度)
对于这种连续数组中求和的情况我们一定要想到前缀和:快速求出数组中某一个连续区间的和
前缀和算法到底是什么?
通过实例来解释:
一维前缀和模板:
- 预处理出来一个前缀和数组dp(小动态规划)
- dp[i]:表示的是 1 ~ i 区间所有元素的和(下标从1开始算,每次创建的数组大小为 n + 1 保证从 1 开始)
- 并且在计算dp数组的过程中,==dp[ i ] = dp[ i - 1] + arr[ i ]==即可算出(具体分析如上图很好理解),这样更快的求出,不需要每次都遍历真个数组!
- 为什么下标从1开始:因为此处要计算 dp[i] 需要使用 dp[i - 1],i 若为0,就会越界,所以从1开始,这样 即使第一个情况下:1 - 1 = 0 也不会越界
- dp[i]:表示的是 1 ~ i 区间所有元素的和(下标从1开始算,每次创建的数组大小为 n + 1 保证从 1 开始)
- 使用前缀和数组
- 当我们得到一个前缀和数组后,假设有下情况:
- 当我们要去 l ~ r 情况的值:就能通过快速的减法得到:dp[ r ] - dp[ l -1 ]
- 算法时间复杂度:O(n) + O(q) = O(n)
- 当我们得到一个前缀和数组后,假设有下情况:
题解核心逻辑:
- 根据题目初始化存储好:n,q,数组,查询区域
- 初始化前缀和数组dp
dp[ i ] = dp[ i - 1] + arr[ i ]
- 使用前缀和数组算出结果
dp[ r ] - dp[ l -1 ]
代码:
#include <iostream>
#include <vector>
using namespace std;int main() {int n , q;cin >> n >> q;long long arr[100010] = {0};//根据题目数量级设置,之前设置超过数量级大小的数组即可long long dp[100010] = {0};for(int i = 1; i <= n;i++){//从1开始因为,前缀和需要下标从1开始,留0位置cin >> arr[i];}vector<vector<long long>> lr;//使用vector存储左右区间lr.resize(q);for(int i = 0 ; i < q;i++){int left,right;cin >> left >> right;lr[i].push_back(left);lr[i].push_back(right);}//1. 使用一维前缀和快速求值://dp[i] = arr[i] + dp[i-1]for(int i = 1; i <= n;i++){dp[i] = arr[i] + dp[i-1];}for(int i = 0 ; i < q;i++){// 使用前缀和求值int l = lr[i][0];int r = lr[i][1];cout << dp[r] - dp[l-1] << endl; }return 0;
}
2. 二维前缀和【模板】
题目:
分析题目并提出,解决方法:
分析题目的例子并理解:
- 第一行是三个数n,m,q
- n:代表矩阵数据的行数,m代表矩阵列数,q代表请求查询的参数
- 其次n行m列的数就是矩阵数据
- 最后的q行数据代表的是:查询的矩阵的左上角和右下角两点,
- 过程中可以将数据看成每两个为一个矩阵中的xy点,这样就能得到两点(x1,y1)、(x2,y2)
如下数据的第一个查询参数值是 1 1 2 2 那么查询的的两点是 (1,1) ~ (2,2)
最终要求的就是这两点矩阵区间的值(如下图)
暴力解法:同样是模拟,根据给的两点的确定查询的矩阵的行列,遍历求和即可
二维前缀和模板:
-
预处理处一个前缀和矩阵
- 创建和原处理矩阵同等大小矩阵dp
- 然后对dp中的值进行设置,此处dp内的值和一维前缀和里的值略有不同也更难理解一丢丢,此处二维的是求从 (1,1) ~ (i, i)内这个小矩阵的和,但直接求发现还是表还是得遍历时间复杂度还是比较高,那么在求的过程中就能不能优化下?可以通过利用之前的dp矩阵得出快速求dp[ i ][ j ] = dp[ i ][ j - 1] + dp[ i-1 ][ j ] + arr[ i ][ j ] - dp[ i - 1 ][ j - 1 ]
具体如下图(注意记住左下角那张分析图,能很好的帮助你理解和记忆公式):
-
如何使用前缀和矩阵快速取出要求的指定矩阵中的值
- 方法类似通过对原矩阵进行分割,通过许多前面算好的矩阵中的值来快速的计算出当前的值,其中划分的步骤很关键,一定要好好理解。
- 为什么划分,为了利用之前的值,并且在划分的过程中使用了更简洁的图来更方便理解!
- 那么如何使用求出指定的区域能,如下图求D区域,找到左下角点和右下角点,分析该如何划分区间,本质就是要考虑两点的关系
- 首先我们可以记住若左上角刚好在整个矩阵的左上角,那么要求的值就是d[x2][y2]的区间的大小
- 那么当左上角不在整个原矩阵最左上角时,对于右下角的值来说需要将左上角之外的多余的值给清除(这样记忆更加的好通过图来记忆公式!)
最终划分出来后如下图(注意记住好左边那张分析图,通过这理解这张图帮助你快速理解和记忆公式)
5.最终得出的所要求的区域值就是: dp[ x2 ][ y2 ] - dp[ x1 - 1 ][ y2 ] - dp[ x2 ][ y1 - 1 ] - dp[ x2 ][ y1 - 1] + dp[ x1 - 1][ y1 - 1 ]
题解核心逻辑:
- 根据题目初始化存储好:n,m,q、矩阵,查询的两点
- 初始化前缀和矩阵dp
dp[ i ][ j ] = dp[ i ][ j - 1] + dp[ i-1 ][ j ] + arr[ i ][ j ] - dp[ i - 1 ][ j - 1 ]
- 使用前缀和数组算出结果
dp[ x2 ][ y2 ] - dp[ x1 - 1 ][ y2 ] - dp[ x2 ][ y1 - 1 ] - dp[ x2 ][ y1 - 1] + dp[ x1 - 1][ y1 - 1 ]
代码:
#include <iostream>
using namespace std;
#include <vector>int main() {int n, m, q;cin >> n >> m >> q;long long arr[1010][1010] = {0};long long dp[1010][1010] = {0};for (int i = 1; i <= n;i++) { //从1开始因为,前缀和需要下标从1开始,留0位置for (int j = 1; j <= m; j++) {cin >> arr[i][j];}}vector<vector<long long>> lr;//使用vector存储左右区间lr.resize(q);for (int i = 0 ; i < q; i++) {int x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;lr[i] = {x1, y1, x2, y2}; //使用initiate}//初始化dp值for (int i = 1; i <= n;i++) { //从1开始因为,前缀和需要下标从1开始,留0位置for (int j = 1; j <= m; j++) {dp[i][j] = arr[i][j] + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];// dp[i][j] = A + B + C + D = D + (A + B) + (A + C)- A}}//使用dp值:for (int i = 0 ; i < q; i++) {int x1 = lr[i][0], y1 = lr[i][1], x2 = lr[i][2], y2 = lr[i][3];cout << dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1] << endl;// D = (x2y2) - B - C - A = (x2y2) - (A+B) - (A+c) + A }return 0;
}
// 64 位输出请用 printf("%lld")
3. 寻找数组的中心下标
题目:
分析题目并提出,解决方法:
分析题目,不难理解示题1的3结果由来:
两种特殊情况:
- 当没有结果时返回 -1
- 默认最左边元素的左半区为0,最右边元素的右边区也为0
- 并且当结果有多个的时候返回最左边的结果
本质所要求的是如下图( i 的左边区间 = i 的右边区间的 i ):
本题本质还是在连续数组中找值,那么我们就能使用前缀和思想:
- 提前预处理好数据到dp中
- 现在需要求的就是 ( 0,i - 1 )、( i + 1,n -1) 这两区间的值
- 前缀和数组:f [ i ] = f [ i - 1 ] + num [ i - 1 ]
- 后缀和数组: g [ j ] = g [ i + 1 ] + num[ i + 1 ]
- 现在需要求的就是 ( 0,i - 1 )、( i + 1,n -1) 这两区间的值
- 利用提前处理好的数组,进行题目要求的判断
- 假设要判断 i 位置的点是否符合条件 那么就等于判断
f[ i ] == g[ i ]
- 假设要判断 i 位置的点是否符合条件 那么就等于判断
题解核心逻辑:
- 创建前缀和数组f:0 ~ i -1、后缀和数组g:i + 1 ~ n - 1
- 通过前面的公式预处理
f[ i ] = f[ i - 1 ] + arr[ i - 1 ]
g[ i ] = g[ i + 1 ] + arr [ i + 1]
- 最后遍历数组,找到
f[ i ] == g[ i ]
处
更多细节见具体代码:
class Solution {
public:static const int CAP = 1e4 + 10;int pivotIndex(vector<int>& nums) {//分析出本题:本质可以通过提前预处理好数组的值来快速计算:前缀和思想//使用前缀和f数组 和 后缀和g数组 存储连续数组的数据int f[CAP] = {0};int g[CAP] = {0};int n = nums.size();//1. 预处理数组//前缀和,f[i] = 0 ~ i - 1for(int i = 1; i <= n;i++){f[i] = f[i-1] + nums[i - 1];//算出 0 ~ i - 1的和}//后缀和,g[i] = i + 1 ~ n - 1for(int i = n - 2;i >= 0;i--){g[i] = g[i+1] + nums[i+1];//g [i] 存储的是 i + 1 ~ n - 1的值//所以当 i = n - 2 存储的就是 n - 1 ~ n - 1的值}//2. 使用预处理数组进行判断for(int i = 0; i < n ;i++)if(f[i] == g[i]) return i;return -1;}
};
4. 除自身以外数组的乘积
题目:
分析题目提出解决方法:
本题本质其实和上一题一样,只不过,本题并不是前缀和,而是前/后 缀积
前缀积、后缀积的算法:
本质也就是将 加法 变成了 乘法(具体如下)
题解核心逻辑:
基本同上就略了
class Solution {
public:static const int CAP = 100010;vector<int> productExceptSelf(vector<int>& nums) {int f[CAP] = {1};//这里是乘法所以等于1int g[CAP];int n = nums.size();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];}//使用预处理好的数组:vector<int> ans(n);for(int i = 0; i < n ;i++){ans.push_back(g[i] * f[i]);}return ans;}
};
5. 和为 K 的子数组
题目:
分析题目提出解决方法:
通过例子分析,题目的目的:
暴力解法,就是枚举所有情况(复杂度O(N2))
分析如何快速找到连续子数组中的值为 k 的子数组
-
先画一个简单的图来分析:不难发现,若要找以 i 结尾的连续子数组,本质是在
0 ~ i - 1
这个区间找一个值为sum[ i ] - k
的值有多少个
(具体如下图,找k长度的区间,可以转换为找sum[ i ] - k 区间的个数,这样就和前面关联了)
-
那如何快速的找出 0 ~ i - 1 区间中 sum[ i ] - k 的个数呢?对于这种数值的查找,可以通过hash表提前存储好
-
具体hash的使用是:每当查找完一个区间后,将当前下标的 sum[ i ] - k 的值存入hash中
-
特殊处理:当
sum[ i ] == k
时,查找的区间就是0 ~ -1
中找 0(sum[i] - k)这本质是不存在的,所以需要提前将hash[0] = 1
,因为区间不存在就无法查找,而此时sum - k = 0
,所以就代表自己这个区间就是符合条件的。 -
其他细节如下:
题解核心逻辑:
- 使用hash表不断记录 0 ~ i - 1 区间中所有sum的情况(因为通过前面的sum情况知道有多少数据为 sum[i] - k)
- 开始遍历数组,判断是否有值等于当前的 sum - k,若有则代表有符合长度的以i结尾的子数组然后记录个数即可
class Solution {
public:int subarraySum(vector<int>& nums, int k) {//存储 0 ~ i - 1 的sum[i] - k个数(注意这本质存的还是0 ~ i - 1区间中每个元素的sum,只是为了找某个值的 sum = 当前sum - k )unordered_map<int,int> hash;hash[0] = 1;//特殊处理int count = 0,sum = 0;for(int i = 0;i < nums.size();i++){sum += nums[i];//if(hash.count(sum - k))count += hash[sum - k];hash[sum]++;}return count;}
};
在本题中同样用到了,前缀和的思想,其中加上了hash来代替前缀和,通过hash代替前缀和中记录前面子数组值,从而实现即记录了子数组的值,右记录了相同子数组值的个数
6. 和可被 K 整除的子数组
题目:
分析题目提出解决方法:
本题和上题类似,本题求的是连续子数组和能被k整除个数(上题是找等于k的个数)
直接本题通过例就能看懂了,并且暴力解法也和上类似就不过诉了!
同余定理
同余定理:通过公式理解(具体如下)(a - b) / p = k (余0) -> a % p = b % p
证明过程…:
c++ / java 的负数取模的结果以及修正
- 负数 % 正数 = 负数 -> 修改为正数:
- 将值a =(a % p + p)% p(这个公式保证了值无论是 整数还是负数最终都能变成正确取余后的整数)
题解核心逻辑:
同上题一样将数组抽象:
若要再0 ~ i - 1区域中查找一个以i结尾的子数组的和的余数 = 0 的子数组个数
得到下图左边的公式:(sum - x) % k = 0
其中就要使用到同余定理得到:sum % k = x % k(从而得到了 x 区域的求法!:sum % k)
所以本题在上题的基础上修改hash中存储的值:存储的就是所有前缀和的余数的个数
- hash[0] = 1;这里处理的是:当 0 ~ i 区间刚好整除 k,那么 此时 sum % k = 0
class Solution {
public:int subarraysDivByK(vector<int>& nums, int k) {unordered_map<int,int> hash;//一个变化的hash:存储 0 ~ i-1 内所有前缀和的余数的个数hash[0] = 1;//这里处理的是:当 0 ~ i 区间刚好整除 k,那么 此时 sum % k = 0int count1 = 0,sum = 0;for(int i = 0; i < nums.size();i++){sum += nums[i];//前缀和// cout << sum << " " << sum % k << " ";if(hash.count((sum % k + k) % k))count1 += hash[(sum % k + k) % k];//查找 sum % k的个数// cout << hash[sum % k] << " "<< count1 << endl;hash[(sum % k + k) % k]++;//添加 / 创建 sum % k的个数 }return count1;}
};
7. 连续数组
题目:
分析题目提出解决方法:
本题关键:将 0 看出 -1
相信如果从上往下做到了该题,那么你已经具备了一定能力了,下面我就不过多叙述; ,还是那句话遇到难题一定要画图分析
具体分析如下图:
题解核心逻辑:
class Solution {
public:int findMaxLength(vector<int>& nums) {//将 0 看出 -1 //求连续子数组中和为0的个数unordered_map<int,int> hash;//存储前缀和的值和下标// 0 ~ i sum
// k = 0, 找前缀和等于 sum - 0 = sum 的个数hash[0] = -1;//此处特殊处理:当 0 ~ i 区间为0的情况下 sum就为0,那么查找的区间是不存在的,所以需要提前设置int sum = 0,count =0;int maxlen = 0;for(int i = 0; i < nums.size();i++){sum += (nums[i] == 1 ? 1 : -1);// hash[sum] if(hash.count(sum)){// cout << sum << " " << hash.count(sum) << " " << hash[sum] <<" ";maxlen = max(maxlen,i - hash[sum]);}if(!hash.count(sum)){//判断是否已经存在,若已经存在则不用再记录了,因为最左区间已经确定hash[sum] = i;// cout << sum << " " << hash[sum]<<endl;}}return maxlen;}
};
8. 矩阵区域和
题目:
分析题目提出解决方法:
一道二维前缀和的题,理解公式轻松解决
其中注意理解题意:本质就是求以(i,j)
为中心的九宫格
分析图如下:
- 其中注意 dp 的下标是从 1 开始的,所以mat中下标都要-1
- 二维前缀和模板
- 而 ans中的小标是从0开始的,所以使用dp时要+1
4. 注意越界问题
题解核心逻辑:
class Solution {
public:vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {//很清楚的二维前缀和int m = mat.size();int n = mat[0].size(); vector<vector<int>> ans(m,vector<int>(n,0));//创建dp表,并预处理得到所有 从 (0,0) ~ (i,j) 区域的和int dp[110][110] = {0};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];cout << dp[i][j] << " ";}cout <<endl;}//最终通过dp表快速的求出所需要的值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;// 求 (x1,y1) ~ (x2,y2) 区域的值给到ans即可ans[i][j] = dp[x2][y2] - dp[x2][y1-1] - dp[x1-1][y2] + dp[x1-1][y1-1];cout << ans[i][j] << " ";}cout << endl;}return ans;}
};
相关文章:
【C/C++算法】从浅到深学习--- 前缀和算法(图文兼备 + 源码详解)
绪论:冲击蓝桥杯一起加油!! 每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 绪论: 本章将使用八道题由浅到深的带你了解并基本掌握前缀和思想,以及前缀和的基…...
VIC模型率定验证
在气候变化问题日益严重的今天,水文模型在防洪规划,未来预测等方面发挥着不可替代的重要作用。目前,无论是工程实践或是科学研究中都存在很多著名的水文模型如SWAT/HSPF/HEC-HMS等。虽然,这些软件有各自的优点;但是&am…...
二叉树的性质和实现
二叉树开端 我们要理解二叉树我们可以先看看什么是树,如图 这个树虽然没有什么叶子,不是很好看,但是用在这里刚刚好,我们从局部来看它,随便挑一根树枝, 大概是这样,由一根粗的的主干和一些细的…...
【Azure 架构师学习笔记】- Azure Databricks (21) --费用相关
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (20) --Delta Live Table 建议 前言 Databricks是很强大的工具和集成平台,但是随着越来越多地使用它,就没办法必须去面…...
StarRocks + Paimon 在阿里集团 Lakehouse 的探索与实践
作者: 范振: 阿里云计算平台开源 OLAP 负责人,StarRocks 社区 Champion 翁才智: 阿里云技术专家,Apache Paimon PMC Member 导读:阿里集团在推进湖仓一体化建设过程中,依托 StarRocks 强大的 OLAP 查询能力与 Paimon…...
OTP单片机调试工具之—单线数据编码
OTP单片机调试工具在实现过程中离不开单线数据的传输,那么使用哪一种方式的数据编码会比较好呢? 我所了解的主要有以下三种: 1.UART(串口),这种方式在单片机和pc之间进行传输都非常常见,效率比较…...
你的完美主义:从缺陷到超能力
所属专栏:《逻辑辨证系列》 前情回顾: 《完美还是完成》(一):完成还是完美—完成大于完美 时间、机会、情绪成本 先完成 … 本期: 《完美还是完成》(二):你的完美主…...
zsh: command not found: adb 报错问题解决
哈喽小伙伴们大家好,我是小李,今天,我满怀信心想要在本地跑一下pda,然而, what? 居然报错了!!别逗我啊! 好吧,究其原因:没有配置好sdk 那就配呗。 首先,…...
应急响应靶机练习-Linux2
1.背景 前景需要:看监控的时候发现webshell告警,领导让你上机检查你可以救救安服仔吗!! 挑战内容: (1)提交攻击者IP (2)提交攻击者修改的管理员密码(明文) (…...
进程间通信--匿名管道
进程间通信介绍 进程间通信目的 数据传输:一个进程需要将它的数据发送给另一个进程资源共享:多个进程之间共享同样的资源。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件&…...
ctfshow-xxs-316-333-wp
316.反射型 XSS(-326都是反射型) js恶意代码是存在于某个参数中,通过url后缀进行get传入,当其他用户点进这个被精心构造的url链接时,恶意代码就会被解析,从而盗取用户信息。 来看题,先简单测试…...
顺序表和链表的对比(一)
前言 今天给小伙伴们分享的是在数据结构中顺序表和链表的对比。它们在计算机科学和软件开发中具有广泛的应用,是理解更复杂数据结构(如栈、队列、树、图等)的基础。这次将会给大家从定义初始化,以及功能增删查改上进行详细对比&a…...
蓝思科技冲刺港股上市,双重上市的意欲何为?
首先,蓝思科技冲刺港股上市,这一举措是其国际化战略进入实质性阶段的重要标志。通过港股上市,蓝思科技有望进一步拓宽融资渠道,这不仅能够为公司带来更加多元化的资金来源,还能够降低对单一市场的依赖风险,…...
【C++项目实战】校园公告搜索引擎:完整实现与优化指南
🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长,行则将至 目录 📚一、项目概述 📖1.项目背景 📖2.主要功能 📖3.界面展…...
C语言每日一练——day_8
引言 针对初学者,每日练习几个题,快速上手C语言。第八天。(连续更新中) 采用在线OJ的形式 什么是在线OJ? 在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中用…...
单片机农业大棚浇花系统
标题:单片机农业大棚浇花系统 内容:1.摘要 本文针对传统农业大棚浇花方式效率低、精准度差的问题,提出了一种基于单片机的农业大棚浇花系统。该系统以单片机为核心控制器,通过土壤湿度传感器实时采集土壤湿度数据,并将数据传输至单片机进行处…...
Kubernetes 单节点集群搭建
Kubernetes 单节点集群搭建教程 本人尝试基于Ubuntu搭建一个单节点K8S集群,其中遇到各种问题,最大的问题就是网络,各种镜像源下载不下来,特此记录!注意:文中使用了几个镜像,将看来可能失效导致安…...
windows安装两个或多个JDK,并实现自由切换
我用两个JDK来做演示,分别是JDK8和JDK17(本人已安装JDK8,所以这里只演示JDK17的安装)。 1、下载JDK17安装 Java Downloads | Oracle 2、安装JDK17,这里忽略。直接双击软件,点击下一步就可以。 3、配置环境变量 在系统变量中新建一个CLASSP…...
如何打包数据库mysql数据,并上传到虚拟机上进行部署?
1.连接数据库,使得我们能看到数据库信息,才能进行打包上传 2. 3. 导出结果如下,是xml文件 4.可以查询每个xml文件的属性,确保有大小,这样才是真实导出 5跟着黑马,新建文件夹,并且把对应的东西放…...
fastapi +angular迷宫求解可跨域
说明:我计划使用fastapi angular,实现迷宫路径生成与求解 后端功能包括: 1.FastAPI搭建RESTful接口。写两个接口, 1.1生成迷宫, 1.2求解路径 前端功能包括 1.根据给定的长宽值,生成迷宫 2.点击按钮&…...
CobaltStrike详细使用及Linux上线
1、工具准备 cs工具 将teamserver.zip放进服务端给必要文件增加可执行文件( 执行时会有提示 )服务端启动服务监听 sudo ./teamserver <IP地址> <密码> [c2配置文件]客户端直接连接即可端口默认:50050主机:服务端ip地址2、基础配置 启动监听…...
WSL2 Ubuntu安装GCC不同版本
WSL2 Ubuntu安装GCC不同版本 介绍安装gcc 7.1方法 1:通过源码编译安装 GCC 7.1步骤 1:安装编译依赖步骤 2:下载 GCC 7.1 源码步骤 3:配置和编译步骤 4:配置环境变量步骤 5:验证安装 方法 2:通过…...
WPF CommunityToolkit.MVVM库的简单使用
CommunityToolkit.MVVM 是 .NET 社区工具包中的一部分,它为实现 MVVM(Model-View-ViewModel)模式提供了一系列实用的特性和工具,能帮助开发者更高效地构建 WPF、UWP、MAUI 等应用程序。以下是关于它的详细使用介绍: 1…...
4个 Vue 路由实现的过程
大家好,我是大澈!一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员👨🏻💻,关注我,科技未来或许我能帮到你! Vue 路由相信朋友们用的都很熟了,但是你知道 Vue 路由…...
Compose 实践与探索十 —— 其他预先处理的 Modifier
1、PointerInputModifier PointerInputModifier 用于定制触摸(包括手指、鼠标、悬浮)反馈算法,实现手势识别。 1.1 基本用法 最简单的使用方式就是通过 Modifier.clickable() 响应点击事件: Box(Modifier.size(40.dp).backgro…...
基于Python的天气预报数据可视化分析系统-Flask+html
开发语言:Python框架:flaskPython版本:python3.8数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 系统登录 可视化界面 天气地图 天气分析 历史天气 用户管理 摘要 本文介绍了基于大数据…...
“消失的中断“
“消失的中断” 1. 前言 在嵌入式开发过程中,中断必不可少。道友们想必也经常因为中断问题头疼不已,今天来说说一个很常见的问题,“消失的中断”。最近项目在使用第三方MCAL的时候,就遇到了I2C中断丢失的问题,排查起…...
对C++面向对象的理解
C的面向对象编程(OOP)是其核心特性之一,通过类(Class)和对象(Object)实现数据和行为的封装,支持继承、多态和抽象等核心概念。以下是关键点解析: 1. 类(Class…...
代码随想录-训练营-day52
97. 小明逛公园 (kamacoder.com) #include<iostream> #include<vector> using namespace std; int main(){int n,m,u,v,w;cin>>n>>m;vector<vector<vector<int>>> grid(n1,vector<vector<int>>(n1,vector<int>(n1…...
Java File 类详解
1. 概述 File 类是 Java 提供的用于文件和目录路径名的抽象表示。它能够用于创建、删除、查询文件和目录的信息,但不用于读写文件内容。如果需要对文件进行读写,可以结合 FileReader、FileWriter、BufferedReader 等类来完成。 2. File 类的构造方法 …...
JS实现省份地级市的选择
JS实现省份地级市的选择 效果展示: 代码实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><ti…...
【鸿蒙开发】Hi3861学习笔记-Visual Studio Code安装(New)
00. 目录 文章目录 00. 目录01. Visual Studio Code概述02. Visual Studio Code下载03. Visual Studio Code安装04. Visual Studio Code插件05. 附录 01. Visual Studio Code概述 vscode是一种简化且高效的代码编辑器,同时支持诸如调试,任务执行和版本管…...
记录致远OA服务器硬盘升级过程
前言 日常使用中OA系统突然卡死,刷新访问进不去系统,ping服务器地址正常,立马登录服务器检查,一看磁盘爆了。 我大脑直接萎缩了,谁家OA系统配400G的空间啊,过我手的服务器没有50也是30台,还是…...
计算机网络-网络规划与设计
基本流程 需求分析—》通信规范分析—》逻辑网络设计—》物理网络设计—》实施阶段 需求分析: 确定需求,包括:业务需求、用户需求、应用需求、计算机平台需求、网络通信需求等。 产物:需求规范 通信规范分析: 现有…...
C#opencv 遍历图像中所有点 不在圆范围内的点变为黑色,在圆范围内的保持原色
C#opencv 遍历图像中所有点 不在圆范围内的点变为黑色,在圆范围内的保持原色 安装 Install-Package OpenCvSharp4 Install-Package OpenCvSharp4.Windows 普通实现 using System; using System.Collections.Generic; using System.Linq; using OpenCvSharp; // 添加OpenCV引用…...
精通游戏测试笔记(持续更新)
第一章、游戏测试的两条规则 不要恐慌 不要将这次发布当作最后一次发布 不要相信任何人 把每次发布当作最后一次发布 第二章:成为一名游戏测试工程师...
Linux内核,mmap_pgoff在mmap.c的实现
1. mmap_pgoff的系统调用实现如下 SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, pgoff) {return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); }2. ksys_mma…...
深度揭秘:蓝耘 Maas 平台如何重塑深度学习格局
目录 前言 深度学习:技术基石与发展脉络 蓝耘 Maas 平台:深度学习的强大助推器 1. 高性能算力支撑 2. 丰富的模型支持 3. 便捷的开发体验 4. 完善的安全保障 代码示例:蓝耘 Maas 平台上的深度学习实践 1. 注册与登录 2. 代码实现 …...
深入解析操作系统进程控制:从地址空间到实战应用
引言 想象这样一个场景: 你的游戏本同时运行着《赛博朋克2077》、Chrome浏览器和Discord语音 突然游戏崩溃,但其他应用依然正常运行 此时你打开任务管理器,发现游戏进程已经消失,但内存占用却未完全释放 这背后涉及的关键机制…...
网络空间安全(33)MSF漏洞利用
前言 Metasploit Framework(简称MSF)是一款功能强大的开源安全漏洞利用和测试工具,广泛应用于渗透测试中。MSF提供了丰富的漏洞利用模块,允许安全研究人员和渗透测试人员利用目标系统中的已知漏洞进行攻击。 一、漏洞利用模块&…...
《Electron 学习之旅:从入门到实践》
前言 Electron 简介 Electron 是由 GitHub 开发的一个开源框架,基于 Chromium 和 Node.js。 它允许开发者使用 Web 技术(HTML、CSS、JavaScript)构建跨平台的桌面应用程序。 Electron 的优势 跨平台:支持 Windows、macOS 和 Linux…...
通达信软件+条件选股+code
在通达信软件中,你的选股公式需要放在 "公式管理器" 的 "条件选股公式" 分类中。以下是详细操作步骤: 一、打开公式管理器 打开通达信软件,按快捷键 Ctrl + F (或点击顶部菜单栏:"公式" → "公式管理器") 二、创建新公式 选择分…...
【2025】基于springboot+vue的汽车销售试驾平台(源码、万字文档、图文修改、调试答疑)
基于 Spring Boot Vue 的汽车销售试驾平台通过整合前后端技术,实现了汽车销售和试驾预约的信息化和智能化。系统为管理员和用户提供了丰富的功能,提升了客户体验和销售效率,增强了数据分析能力,为汽车销售行业的发展提供了新的途…...
Spring Web MVC入门
一、什么是SpringMVC 首先,MVC是一种架构设计模式,也是一种思想,而SpringMVC是对MVC思想的具体实现,除此之外,SpringMVC还是一个Web框架。 总的来说,SpringMVC就是一个实现MVC模式的Web框架。 而MVC可以…...
5G核心网实训室搭建方案:轻量化部署与虚拟化实践
5G核心网实训室 随着5G技术的广泛应用,行业对于5G核心网人才的需求日益增长。高校、科研机构和企业纷纷建立5G实训室,以促进人才培养、技术创新和行业应用研究。IPLOOK凭借其在5G核心网领域的深厚积累,提供了一套高效、灵活的5G实训室搭建方…...
IMX6ULL学习整理篇——Linux驱动开发的基础2 老框架的一次实战:LED驱动
IMX6ULL学习整理篇——Linux驱动开发的基础2 老框架的一次实战:LED驱动 在上一篇博客中,我们实现了从0开始搭建的字符设备驱动框架,但是这个框架还是空中楼阁,没有应用,很难说明我们框架的正确性。这里,…...
网络空间安全(32)Kali MSF基本介绍
前言 Metasploit Framework(简称MSF)是一款功能强大的开源安全漏洞检测工具,被广泛应用于渗透测试中。它内置了数千个已知的软件漏洞,并持续更新以应对新兴的安全威胁。MSF不仅限于漏洞利用,还包括信息收集、漏洞探测和…...
零基础上手Python数据分析 (3):Python核心语法快速入门 (下) - 程序流程控制、函数与模块
写在前面 还记得上周我们学习的 Python 基本数据类型、运算符和变量吗? 掌握了这些基础知识,我们已经能够进行一些简单的数据操作了。 但是,在实际的数据分析工作中,仅仅掌握基本语法是远远不够的。 我们需要让程序能够 根据条件做出判断,重复执行某些操作,组织和复用代…...
C++【类和对象】(超详细!!!)
C【类和对象】 1.运算符重载2.赋值运算符重载3.日期类的实现 1.运算符重载 (1).C规定类类型运算符使用时,必须转换成调用运算符重载。 (2).运算符重载是具有特殊名字的函数,名字等于operator加需要使用的运算符,具有返回类型和参数列表及函数…...
Windows-PyQt5安装+PyCharm配置QtDesigner + QtUIC
个人环境 Windows 11 pycharm 2024.2 Anaconda2024.6python 3.9 1)先使用pip命令在线安装 1)pip install PyQt5 2)pip install PyQt5-tools2)配置环境变量 1:安装成功后可以在python的安装目录Lib\site-packahes目录下看到安装包。比如我的路径是E:\anaconda3…...