当前位置: 首页> 科技> 能源 > 微信怎么建立公众号小程序_闵行区新闻网网站_清远新闻最新消息_爱站网seo工具

微信怎么建立公众号小程序_闵行区新闻网网站_清远新闻最新消息_爱站网seo工具

时间:2025/7/30 7:16:28来源:https://blog.csdn.net/qq_45678698/article/details/146077398 浏览次数:0次
微信怎么建立公众号小程序_闵行区新闻网网站_清远新闻最新消息_爱站网seo工具

利用前缀和:快速找到所有满足要求的子数组数量&&变种问题

  • 何为前缀和:对数组元素做累加和
  • 如何用前缀和在一次O(N)找到所有符合要求的子数组数量?
    • 步骤 1 :求出前缀和(见第一节)
    • 步骤 2 :在前缀和上进行遍历,找到所有目标值
    • 步骤 3 :循环次数优化
    • 步骤 4 :初始值
    • 实现
  • 变种问题(同类问题,加一些帽子)
    • 步骤 1 :转化问题
    • 步骤 2 :套用上一题
    • 步骤 3 :实现

何为前缀和:对数组元素做累加和

按照以下示例展示前缀和计算方法:
注意!!!!:前缀和数组第一个元素永远都是0,累加和从第二处开始添加

应用场景:求任意子数组 / 求数组内任意一个连续范围内 的和

初始状态:
1、nums = [1, 1, -1, 1, -1]
2、前缀和数组 s = [0, 0, 0, 0, 0, 0]。这是因为我们需要一个多一位的数组,其中 s[0] = 0 代表没有元素的前缀和。

计算前缀和数组 s:
迭代1:
nums[0] = 1,计算 s[[1]]= s[0] + 1 = 0 + 1 = 1,前缀和更新为 s = [0, 1, 0, 0, 0, 0]。
迭代2:
nums[[1]] = 1,计算 s[[2]] = s[[1]] + 1 = 1 + 1 = 2,前缀和更新为 s = [0, 1, 2, 0, 0, 0]。
迭代3:
nums[[2]] = -1,计算 s[[3]] = s[[2]] + (-1) = 2 - 1 = 1,前缀和更新为 s = [0, 1, 2, 1, 0, 0]。
迭代4:
nums[[3]] = 1,计算 s[[4]] = s[[3]] + 1 = 1 + 1 = 2,前缀和更新为 s = [0, 1, 2, 1, 2, 0]。
迭代5:
nums[[4]] = -1,计算 s[[5]] = s[[4]] + (-1) = 2 - 1 = 1,前缀和更新为 s = [0, 1, 2, 1, 2, 1]。

如何用前缀和在一次O(N)找到所有符合要求的子数组数量?

我们以 力扣560. 和为 K 的子数组 为例对该问题进行求解
在这里插入图片描述

步骤 1 :求出前缀和(见第一节)

步骤 2 :在前缀和上进行遍历,找到所有目标值

如何在前缀和上找到任意一个子数组的和:s[j] - s[i] = SUM
本题要求和为K,所以转化成:s[j] - s[i] = k
1、一个朴素的想法就是,枚举J的位置,再从0处枚举i,找到一个前缀和s[i]的值满足:s[i] = s[j] - k
2、但是显而易见的,复杂度=O(n^2),对于本题而言不可以,那么有没有什么办法可以省略掉第二次循环?
3、第二次循环的目的是什么?找到满足要求的所有s[i]的数量,所以我们动态维护就好了,采用一个字典维护出现过的所有前缀和的值以及他们的出现次数,这样就可以在O(1)的时间内得到满足要求的数量
4、这时,只需要遍历完所有元素,累加出的和即为答案。

步骤 3 :循环次数优化

很显然,对于每次的s[j]前面的元素,我已经不需要存储在数组中,只需要维护在HashMap中即可,我每次先更新此处的前缀和值,再根据s[i] = s[j] - k 找到s[i]的值,最后去HashMap中找到s[i]出现了几次,最后做累加即可。所以显而易见的,可以边算前缀和边统计

步骤 4 :初始值

满足上述计算条件,需要从nums[0]也就是s[1]开始,所以要把s[0]=0初始状态加到HashMap中,即初始值HashMap[0] = 1

实现

class Solution {
public:int subarraySum(vector<int>& nums, int k) {int ans = 0;unordered_map<int, int> cnt{ { 0,1 } };//注意写法int s = 0;for (int x : nums) {s += x;//先计算此处前缀和的值ans += cnt.find(s - k) == cnt.end() ? 0 : cnt[s - k];//在寻找s[i]出现几次,这里注意,不要直接调用cnt[s - k],因为没有cnt[s - k]的话会插入cnt[s]++;//s出现次数多一次,在字典中为其更新}return ans;}
};

变种问题(同类问题,加一些帽子)

我们以 力扣2588. 统计美丽子数组数目 为例对该问题进行求解
在这里插入图片描述

步骤 1 :转化问题

很明显的,从十进制看不出任何规律,并且,题目中明确提示了二进制,所以把例一转化一下,把每个数都写成二进制:

													100011001010100

​我们此时再看例一中两个符合要求的组,很明显的,以[4,3,1,2,4]为例,我们发现各个列都是2个1,另一个美丽子数组也同样。所以,很明显,体重操作就是执行异或操作,只要选择的数如上述摆放,每一列偶数个1就满足要求。

换句话说:满足要求的子数组,其所有元素的异或和 = 0

所以本题转化为:找到满足子数组所有元素异或和 = 0的子数组个数

步骤 2 :套用上一题

把上一题中 k 设置为 0 即可
+ 运算改为 ^ 即可

步骤 3 :实现

class Solution {
public:long long beautifulSubarrays(vector<int>& nums) {long long ans = 0;unordered_map<int, int> cnt{{0, 1}};int s = 0;for (int x : nums) {s ^= x;ans += cnt[s - 0]++;}return ans;}
};
关键字:微信怎么建立公众号小程序_闵行区新闻网网站_清远新闻最新消息_爱站网seo工具

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: