前缀和
前缀和
通常,涉及连续子数组问题的时候,我们使用前缀和来解决。
- 我们令 P[i] = A[0] + A[1] + … + A[i]
- 那么每个连续子数组的和 sum(i, j) = P[j] - P[i-1](其中 0 < i < j)。
例如:
| 1 | public int subarraySum(int[] nums, int k) { | 
前缀和+同余定理 p[j]- p[i] % K = 0 等价于 p[j] % k == p[i] % K1
2
3
4
5
6
7
8
9
10
11
12
13public int subarraysDivByK(int[] A, int K) {
	int sum = 0, res = 0;
	Map<Integer, Integer> map = new HashMap<>();
	map.put(0, 1);
	for (int n : A) {
		sum += n;
		int curMod = (sum%K+K)%K;   // 变负为正
		int preCount = map.getOrDefault(curMod, 0);
		res += preCount;
		map.put(curMod, preCount + 1);
	}
	return res;
}
若K的数量级不高可以用数组代替map
| 1 | public int subarraysDivByK(int[] A, int k) { | 
类似前缀和的前缀积
- 由于是前缀积,所以一般不像前缀和是正负波动的,而是递增的,且数量大
- 所以不能用存储记录,而是用(滑动窗口)
例如:
前缀积 + 滑动窗口1
2
3
4
5
6
7
8
9
10
11
12
13public int numSubarrayProductLessThanK(int[] nums, int k) {
	if(k<=1) return 0;
	int res = 0,sum = 1,l = 0;
	for (int r = 0; r <nums.length ; r++) {
		sum *= nums[r];
		while (sum >= k){
			sum /= nums[l];
			l++;
		}
		res += (r-l+1);
	}
	return res;
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Kid1999' Blog!




