满足长度等于P倍元素和的子数组查找及问题归类咨询
符合条件子数组统计问题解答
1. 高效校验统计方案
核心推导
暴力枚举所有子数组的时间复杂度为O(N²),无法处理N=1e5的规模,我们可以通过数学转换将问题降为线性时间复杂度:
设前缀和数组S,其中S[0] = 0,S[k]为数组前k个元素的和(即A[0]到A[k-1]的和)。对于任意子数组A[i...j](闭区间,长度为j-i+1),其元素和为S[j+1] - S[i],代入题目要求的规则:
子数组长度 = P * 子数组元素和
可得等式:j - i + 1 = P * (S[j+1] - S[i])
移项后将相同下标的项放在同侧,可得:P * S[j+1] - (j+1) = P * S[i] - i
此时问题转换为:遍历每个右边界r = j+1,统计此前所有位置中,P*S[i] - i的值等于当前P*S[r] - r的出现次数,该次数即为以r为结尾的符合条件的子数组数量,累加所有次数即可得到总数量。
特殊情况处理
- 当
P=0时,原等式右侧恒为0,而子数组长度最小为1,此时不存在符合条件的子数组,直接返回0即可。 - 所有计算值需使用
long类型存储,避免前缀和叠加、乘以P后超出int范围导致溢出。
复杂度说明
时间复杂度O(N):仅需遍历数组一次,哈希表的存取操作均为O(1)均摊复杂度。
空间复杂度O(N):最坏情况下所有P*S[i] -i的值均不重复,哈希表需要存储N个键值对。
2. 问题分类说明
该问题属于P类问题,不属于NP-hard问题:我们已经找到了确定性的线性时间复杂度解法,可在多项式时间内得到结果,远低于NP-hard问题的求解难度。该问题属于经典的「前缀和+哈希表优化」类子数组计数问题。
C# 实现代码
using System; using System.Collections.Generic; public class Solution { public static long CountValidSubarrays(int[] A, int P) { if (A == null || A.Length == 0 || P == 0) { return 0; } long prefixSum = 0; long count = 0; Dictionary<long, int> keyCount = new Dictionary<long, int>(); // 初始化前缀和为0的边界情况 keyCount.Add(0, 1); for (int r = 1; r <= A.Length; r++) { prefixSum += A[r - 1]; long currentKey = (long)P * prefixSum - r; if (keyCount.ContainsKey(currentKey)) { count += keyCount[currentKey]; keyCount[currentKey]++; } else { keyCount.Add(currentKey, 1); } } return count; } // 测试用例 public static void Main() { int[] A = new int[] {2, -1, 3, 0, 1, 2, 1}; int P = 2; Console.WriteLine(CountValidSubarrays(A, P)); // 输出2,与示例结果匹配 } }
内容的提问来源于stack exchange,提问作者user1907849
相关产品推荐
相关产品推荐

