admin管理员组文章数量:1438858
深度解析算法之前缀和
25.【模版】一维前缀和
题目链接 描述
输入描述
输出描述 输出q行,每行代表一次查询的结果.
示例
输入:
3 2 1 2 4 1 2 2 3
复制
输出:
3 6
这个题的话就是下面的样子,我们第一行输入 3 2的意思即是这个数组是3个元素大小的数组,2是接下来我们是需要输入两行数据下标的 然后第二行我们输入的n个整数表示的就是我们数组中的元素 然后后面的2行就是我们想计算数组中从哪里到哪里的和 这里的话我们是第一个数到第二个数的和,那么我们这里的就是3了
如果我们使用暴力解法解决这个题的话,那么我们的时间复杂度会超的
所以我们这里需要使用算法:前缀和,这个算法可以快速得出我们的某一段区间之和的大小的,我们这个算法的时间复杂度只需要O(1)
我们第一步:预处理出来一个前缀和数组dp dp[i]表示:表示[1,i]区间内所有的元素的和 dp[3]就表示的是这个位置存放的时候我们数组第一个元素到第三个元素的和
dp[3]=dp[2]+arr[3],因为我们现在要求前三个位置的和,我们的dp[2]已经求出来了,那么我们直接加上第三个数就行了
dp[i]=dp[i-1]+arr[i]
那么现在我们已经处理出来了一个前缀和数组
那么现在我们就需要使用我们前缀和数组了 现在如果我们需要算出3到5区间的和,那么我们可以先求出1-5区间的和,然后再算出1-2区间的和,再由前者减去后者,就得到了我们的要的结果了
那么我们现在需要求出[l,r]区间的大小,那么我们可以推理出,这段区间的大小等于 dp[r]-dp[l-1]
疑问:为什么我们的dp下标从1开始计数 假设我们想求出[0,2]区间的大小的话,那么利用dp我们就得到==dp[2]-dp[-1] ==很明显这个越界了
但是如果我们从1开始的话,那么最终结果是不会被干扰的,一切是正常的
之所以这么设置的话就是为了处理边界情况
代码语言:javascript代码运行次数:0运行复制#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);//设置为long long 防止移除的问题
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;
}
26.【模版】二维前缀和
题目链接 描述
给你一个 n 行 m 列的矩阵 A ,下标从1开始。
接下来有 q 次查询,每次查询输入 4 个参数 x1 , y1 , x2 , y2
请输出以 (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和,
**输入描述:
第一行包含三个整数n,m,q.
接下来n行,每行m个整数,代表矩阵的元素
接下来q行,每行4个整数x1, y1, x2, y2,分别代表这次查询的参数
1≤n,m≤10001≤n,m≤1000 1≤q≤1051≤q≤105 −109≤a[i][j]≤109−109≤a[i][j]≤109 1≤x1≤x2≤n1≤x1≤x2≤n 1≤y1≤y2≤m1≤y1≤y2≤m
**输出描述:
输出q行,每行表示查询结果。
**示例1
输入: 3 4 3 1 2 3 4 3 2 1 0 1 5 7 8 1 1 2 2 1 1 3 3 1 2 3 4 输出:8 25 32
我们输入3 4 3第一个三就是三行,四就是四列,第二个三就是三次询问 我们这里输入的下面三行的数据就是我们想要求和区间的坐标 (1,1)~(2,2)->1+2+3+2=8
(1,1)~(3,3)->1+2+3+3+2+1+1+2+7= 25
(1,2)~(3,4)->2+3+4+2+1+0+5+7+8=32
我们这里依旧使用前缀和进行问题的解决
1.预处理出来一个前缀和矩阵 重新创建一个矩阵,这个矩阵的规模和之前矩阵的规模一样
dp [i] [j]表示的是从(1,1)到位置[i,j]位置,这段区间里面所有元素的和
我们得先想一个方法快速求出这个dp的值是多少
dp [i] [j] =A+B+C+D =A+B +A+C +D -A =dp [i-1] [j] +dp[i] [j-1] +arr[i] [j]-dp [i-1] [j-1]
2.使用前缀和矩阵
最后的面积等于 dp[x2] [y2]-dp[x1-1] [y2]- dp[x2] [y1-1] +dp[x1-1] [y1-1]
代码语言:javascript代码运行次数:0运行复制#include <iostream>
#include<vector>
using namespace std;
int main()
{
//1.先读入数据
int n=0,m=0,q=0;
cin>>n>>m>>q;
vector<vector<int>>arr(n+1,vector<int>(m+1));//n+1行,m+1列
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>arr[i][j];//将我们输入的数据放到数组中去
}
}
//2.预处理前缀和矩阵
vector<vector<long long >>dp(n+1,vector<long long>(m+1));//n+1行,m+1列,long long防止溢出
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;
}
27.寻找数组的中心下标
题目链接
给你一个整数数组 nums
,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为 0
,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1
。
示例 1:
输入: nums = [1, 7, 3, 6, 5, 6] 输出: 3 解释: 中心下标是 3 。 左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 , 右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
示例 2:
输入: nums = [1, 2, 3] 输出:-1 解释: 数组中不存在满足此条件的中心下标。
示例 3:
输入: nums = [2, 1, -1] 输出: 0 解释: 中心下标是 0 。 左侧数之和 sum = 0 ,(下标 0 左侧不存在元素), 右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。
利用前缀和解决这个问题
我们利用前缀和的方式将i的前缀和和后缀和都求出来,来进行比较
预处理: f:前缀和数组:f[i]表示:[0,i-1]区间,所有元素的和 f[i]=f[i-1]+nums[i-1]
g:后缀和数组:g[i]表示[i+1,n-1]区间,所有元素的和 g[i]=g[i+1]+nums[i+1]
如何使用 我们枚举出0~n-1中所有的下标,然后带进去
细节问题,当我们将f[0]带进去的话是会出现问题的,会出现越界的情况, g[n-1]这个位置也会出现问题
我们两个边界问题得提前处理下
代码语言:javascript代码运行次数:0运行复制class Solution {
public:
int pivotIndex(vector<int>& nums)
{
int n=nums.size();
vector<int>f(n),g(n);//一个是前缀和数组,一个是后缀和数组
//这里我们已经将f(n)、g(n)初始化为0了,避免边界问题
//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;
}
};
先预处理前缀和数组以及后缀和数组,然后再枚举所有的可能进行判断
28.除自身以外数组的乘积
题目链接
给你一个整数数组 nums
,返回 数组 answer
,其中 answer[i]
等于 nums
中除 nums[i]
之外其余各元素的乘积 。
题目数据 保证 数组 nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请 不要使用除法, 且在 O(n)
时间复杂度内完成此题。
示例 1:
输入: nums = [1,2,3,4]
输出: [24,12,8,6]
示例 2:
输入: nums = [-1,1,0,-3,3] 输出: [0,0,9,0,0]
我们想计算i位置除自身外的乘积,那么我们分别把前面的i-10位置的和i+1n-1位置的乘积之和计算出来。
预处理前缀积和后缀积 f:表示前缀积 f[i]表示:[0,i-1]区间内所有元素的乘积 f[i]=f[i-1] * nums[i-1] g:表示后缀积 g[i]=g[i+1]* nums[i+1]
使用,我们直接return f[i]* g[i]就行了
处理细节问题 f[o]和g[n-1],我们这里需要将这两个设置为1,避免越界问题
代码语言:javascript代码运行次数:0运行复制class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums)
{
int n=nums.size();
vector<int>f(n),g(n);
//1.预处理前缀积数组和后缀积数组
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];
}
//使用前缀积数组和后缀积数组
vector<int>ret(n);
for(int i=0;i<n;i++)
{
ret[i]=f[i]*g[i];
}
return ret;
}
};
29.和为 K 的子数组
题目链接
给你一个整数数组 nums
和一个整数 k
,请你统计并返回 该数组中和为 k
的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入: nums = [1,1,1], k = 2 输出: 2
示例 2:
输入: nums = [1,2,3], k = 3 输出: 2
这个题是不能使用双指针滑动窗口做优化的
我们只需要找到i位置前面,就是[0,i-1]位置中间,有多少个前缀和等用户sum[i]-k的
我们利用哈希表记录我们前缀和出现的次数
细节问题 前缀和加入哈希表的时机,在计算i位置之前,哈希表里面只保存[0,i-1]位置的前缀和,当我们计算玩i位置之后的,我们再将这个丢到哈希表里面去
我们 不用真的创建一个真的前缀和数组,我们只需要用一个变量sum来标记前一个位置的前缀和即可
如果整个前缀和等于k呢?那我们按照我们上面的逻辑的话,是不是要到[0,-1]这个区间去找呢? 这个区间很明显是违法了的,不存在
所以我们在创建哈希表的时候,我们需要将hash[0]=1丢到哈希表中 如果整个数组等于k的话,那么我们最后返回的结果就是1
代码语言:javascript代码运行次数:0运行复制class Solution {
public:
int subarraySum(vector<int>& nums, int k)
{
unordered_map<int,int>hash;//统计前缀和出现的次数
hash[0]=1;
int sum=0,ret=0;//sum用来标记我们的前缀和
for(auto x:nums)
{
sum+=x;//记录当前位置的前缀和
//寻找当前位置之前一共有多少个sum-k
//如果我们当前位置前面存在sum-k的话,那么我们就记录我们此时sum-k出现的次数
if(hash.count(sum-k))ret+=hash[sum-k];//统计sum-k出现次数并惊醒统计操作
hash[sum]++;//将当前的前缀和 sum 出现次数加一,更新哈希表。
}
return ret;
}
};
//该算法的时间复杂度是 O(n),其中 n 是数组的长度。因为我们只遍历一次数组,且每次查找哈希表中的值和插入新值的操作时间复杂度为 O(1)。
//总结:这是一个高效的解决子数组和为 k 问题的算法,利用哈希表记录前缀和的出现次数,可以在 O(n) 时间内得到答案。
利用哈希表记录我们当前位置前面出现sum-k的次数就能判断我们前缀和为k出现的次数 我们这里只遍历了一次数组,就将每个位置前面sum-k出现的次数都记录下来了
30.和可被 K 整除的子数组
题目链接
给定一个整数数组 nums
和一个整数 k
,返回其中元素之和可被 k
整除的非空 子数组 的数目。
子数组 是数组中 连续 的部分。
示例 1:
输入: nums = [4,5,0,-2,-3,1], k = 5 输出: 7 解释: 有 7 个子数组满足其元素之和可被 k = 5 整除: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
示例 2:
输入: nums = [5], k = 9 输出: 0
同余定理
a对p取得余数就等于b对p取的余数,前提是(a-b)除以p=k。。。。0
下面是我们在c++和java中处理负数的情况,
(sum-x)%k=0->sum%k=x%k 就是在[0,i-1]区间内,找到有多少个前缀和的余数等于sum%k 但是这里的话可能是负数,所以我们需要对余数进行修正==(sum%k+k)%k==
所以这个题就是在[0,i-1]区间内,找到有多少个前缀和的余数等于==(sum%k+k)%k==
我们这里不需要存储前缀和,我们存储前缀和的余数就行了 这里我们使用哈希表进行存储 hash<int ,int>左边的int表示的前缀和的余数,右边的int表示的是这个余数出现的次数
代码语言:javascript代码运行次数:0运行复制class Solution {
public:
int subarraysDivByK(vector<int>& nums, int k)
{
unordered_map<int,int>hash;
hash[0%k]=1;//我们需要将前缀和为0的这个提前进行处理,如果不处理的话后面带入到代码会出错的
//这里的0也是余数,0%k=0,余数为0出现的次数,我们这里存的是0这个数的余数
int sum=0,ret=0;//使用sum标记当前位置前面的前缀和
for(auto x:nums)
{
sum+=x;//算出当前位置的前缀和
int r=(sum%k+k)%k;//修正后的余数,对正数、负数都有效的
if(hash.count(r)) ret+=hash[r];//统计余数出现的次数
hash[r]++;
}
return ret;
}
};
- 前缀和:我们计算数组每个位置的前缀和
sum
,即sum[i]
表示从数组开始到第i
个位置的所有元素的和。 - 取余操作:为了找到和为
k
的子数组,我们需要通过前缀和的差来判断。具体来说,子数组的和sum[i] - sum[j]
能被k
整除,即sum[i] % k == sum[j] % k
。 - 哈希表:我们使用哈希表(
unordered_map
)来存储前缀和对k
取余的结果。哈希表的键是余数,值是该余数出现的次数。如果一个余数重复出现,就说明在这两个位置之间存在一个和为k
的子数组。 - 处理负数:由于前缀和可能是负数,我们使用
(sum % k + k) % k
来确保余数始终为非负数,这样可以正确处理负数的情况。 - 初始条件:我们初始化哈希表
hash[0 % k] = 1
,用来处理前缀和从数组开始就能被k
整除的情况。 -
sum % k
: 这是对sum
进行模k
运算,得到的结果可能是负数(当sum
是负数时)。 比如,假设sum = -3
,而k = 5
,那么-3 % 5
的结果是-3
,这是负数。 -
sum % k + k
: 这是将得到的负余数加上k
,目的是将负数转为正数。 继续上面的例子,-3 + 5 = 2
。这时,我们得到了一个正数余数。 -
(sum % k + k) % k
: 这一步再对结果进行一次模k
运算,确保余数始终在0
到k-1
之间。虽然前面的加k
已经将负数转为正数,但我们还是要确保结果不超过k-1
。 例如,(2 % 5) = 2
。如果sum % k + k
的结果已经在0
到k-1
范围内,第二次% k
操作不会改变结果。 假设sum = -3
且k = 5
: -
sum % k = -3 % 5 = -3
-
sum % k + k = -3 + 5 = 2
-
(sum % k + k) % k = 2 % 5 = 2
31.连续数组
题目链接
给定一个二进制数组 nums
, 找到含有相同数量的 0
和 1
的最长连续子数组,并返回该子数组的长度。
示例 1:
输入: nums = [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
示例 2:
输入: nums = [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
对于这个数组来说的话,如果我们将上面数组中的0变-1,然后我们在下面数组中进行匹配,1和-1相加,那么结果就是0,那么问题就变成了在数组中找到一个连续的子数组,让这个子数组中的值的和是0就可以了
解法:前缀和+哈希表
哈希表中存什么 hash<int,int>,第一个int是前缀和,第二个int存的是下标
什么时候存入哈希表? 使用完之后丢进哈希表
如果有重复的<sum,i>,如何存呢? 只保存前面的那一对<sum,i>
默认的前缀和为0的情况,如何存呢? 我们在之前的话是会进行处理的hash[0]=1 但是这里的话我们存的是下标 我们的处理就是hash[0]=-1
长度怎么算呢? 数组的总长度为sum,我们想找一个子区域和为0,那么这个子区域的前面的前缀和的大小就是sum
长度为i-j
代码语言:javascript代码运行次数:0运行复制class Solution {
public:
int findMaxLength(vector<int>& nums)
{
unordered_map<int,int>hash;//我们hash表之中存的是前缀和和下标
hash[0]=-1;//此时的下标为-1,默认有一个前缀和为0的情况
int sum=0,ret=0;//sum来标记当前位置前面的前缀和
for(int i=0;i<nums.size();i++)
{
sum+=nums[i]==0?-1:1;//计算当前位置的前缀和,如果此时我们当前位置的值是0的话,那么我们加的就是-1,否则的话就是1
if(hash.count(sum)) ret=max(ret,i-hash[sum]);//找到我们前缀和为sum的位置并且进行更新,只要出现了sum的话,那么我们就进行更新的操作
//如果 `sum` 出现过,这意味着从上次出现 `sum` 的位置到当前的位置 `i` 之间,数组的 `0` 和 `1` 数量相等。
//这里就是不存在的情况
//如果以前不存在sum的话,那么现在的i就是第一个sum的起始下标
else hash[sum]=i;
}
return ret;
}
};
hash[0] = -1;
这行代码初始化了哈希表,假设在索引 -1
处有一个前缀和为 0
。这是为了处理一些特殊情况,比如如果从数组的开头到某个位置的前缀和已经为零,我们可以计算出该段子数组的长度。
sum+=nums[i]== 0?-1:1; 如果我们当前的位置i的数字的大小是0的话,那么我们让这个位置的数变成-1 就是给总和加上了-1 这个就和我们转换的题目对应上了 将数组中原本的0变成-1 如果当前位置的数不是0的话,那么我们就让总和加上1
i - hash[sum] i是当前的位置,hash[sum]是第一次出现前缀和sum的地方
假设数组是 [0, 1, 0, 1, 0]
,我们已经将 0
转换为 -1
,得到数组 [-1, 1, -1, 1, -1]
。
- 遍历过程:
i = 0
,sum = -1
,hash[-1]
没有出现过,存入hash[-1] = 0
。i = 1
,sum = 0
,hash[0]
没有出现过,存入hash[0] = 1
。i = 2
,sum = -1
,hash[-1]
已经出现,hash[-1] = 0
,所以子数组的长度是i - hash[-1] = 2 - 0 = 2
,这是一个有效的子数组,包含相同数量的0
和1
。i = 3
,sum = 0
,hash[0]
已经出现,hash[0] = 1
,所以子数组的长度是i - hash[0] = 3 - 1 = 2
。i = 4
,sum = -1
,hash[-1]
已经出现,hash[-1] = 0
,所以子数组的长度是i - hash[-1] = 4 - 0 = 4
,更新ret = 4
。 在这里,i - hash[sum]
是计算子数组的长度,而不是i - hash[sum] + 1
,是因为哈希表中保存的是索引位置,而我们要计算的是子数组的元素个数,而索引是从 0 开始的。
31.矩阵区域和
题目链接
给你一个 m x n
的矩阵 mat
和一个整数 k
,请你返回一个矩阵 answer
,其中每个 answer[i][j]
是所有满足下述条件的元素 mat[r][c]
的和:
i - k <= r <= i + k,
j - k <= c <= j + k
且(r, c)
在矩阵内。
示例 1:
输入: mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1 输出:[[12,21,16],[27,45,33],[24,39,28]]
示例 2:
输入: mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2 输出:[[45,45,45],[45,45,45],[45,45,45]]
题目要求返回和原始矩阵相同规模的矩阵 在k=1的情况下,以mat数组为基础,我们的answer[0] [0]的大小j就是以mat[ 0] [0]为中心扩展一个格子的区域的总和,如果超出边界,那么超出边界的部分不算,那么我们这里的answer[0] [0]=12
这个题起始就是快速求出某个区域的和,就是在求二维数组前缀和的基础上进行改变 对于右下角区域的和 dp[i] [j] =dp[i-1] [j]+dp[i] [j-1]-dp[i-1] [j-1] +mat[i] [j]
我们在求ans[i] [j]的时候,需要向四周扩展k个单位。如果中间点的坐标是[i] [j]的话,那么左上角的坐标就是[i-k] [j-k] 右下角的坐标是[i+k] [j+k]
如果我们的[i-k]<0的话,那么我们就需要回归到(0,0)这个位置的,因为我们是不能进行越界的 所以我们对左上角的坐标定义为:x1=max(0,i-k),如果i-k小于0的话,那么x1=0,这种就可以处理边界情况,对0处理max就行了 同理我们右下角的一样是可以同样的处理方式 m和n是这个矩阵的长度和宽度 右下角的话可能大于(m-1,n-1),如果x2的坐标大于(m-1,n-1)的话,那么我们直接让x2定义为(m-1,n-1)
那么我们现在求出来中心点右上角和右下角的坐标,那么我们直接带入上面的ret的公式就可以求出我们最终的结果了
下标的映射关系 我们dp表是从(1,1)开始的 如果我们在填dp表的时候我们下标是要-1的
最后我们需要在ans表中使用dp表的时候,我们的坐标是要+1的
我们在求ans[i] [j]的时候直接在这里的下标处进行+1的操作,因为在ret那里加的话很麻烦的
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));//m+1行,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];//这里的mat下标是修改过的,因为我们的dp数组从(1,1)位置开始的,我们这里的mat的下标-1是为了处理下标的映射关系的
}
}
//那么到这里的话我们前缀和的数组就搞定了,下面就是使用前缀和的数组了
vector<vector<int>>ret(m,vector<int>(n));//最终的结果是和原始的矩阵同等的规模的
//我们需要将这个矩阵填上
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
//我们需要求出当前的(i,j)坐标左上角和右下角的坐标来进行求和
//这个是左上角的坐标
int x1=max(0,i-k)+1,y1=max(0,j-k)+1;//这里的+1是为了在dp表中找位置的,正好可以在dp表中找到对应的位置
int x2=min(m-1,i+k)+1,y2=min(n-1,j+k)+1;
//现在我们将当前的(i,j)坐标左上角和右下角的位置都找到了,那么我们直接返回结果了
ret[i][j]=dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1];
}
}
return ret;
}
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2025-04-20,如有侵权请联系 cloudcommunity@tencent 删除算法intsum数据数组本文标签: 深度解析算法之前缀和
版权声明:本文标题:深度解析算法之前缀和 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1747600117a2726765.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论