前缀和 01

157 阅读1分钟

LeetCode 560

原题链接

代码如下:

/**
 * 前缀和
 * 
 * 定义 pre[i] 是 [0,i]内所有数的和,所以 pre[i] = pre[i - 1] + nums[i]
 * [j,i]内的子数组和等于k,可以转化为: pre[i] - pre[j - 1] == k
 * 所以符合条件的下标j需要满足:pre[j - 1] == pre[i] - k
 * 所以我们考虑以 i结尾的和为 k的连续子数组个数时只要统计有多少个前缀和为pre[i]-k和pre[j]即可
 * 我们建立哈希表 mp,以和为键,出现次数为对应的值,记录pre[i]出现的次数,从左往右更新mp
 * 边计算答案,那么以i结尾的答案mp[pre[i] - k]即可在O(1)时间内得到,最后的答案就是所有下标结尾的和
 * 为k的子数组个数之和
 * 
 * Note: 从左往右边更新计算的时候已经保证了pre[pre[i] - k]里记录的pre[j]的下标范围是j∈[0,i]
 * 		同时由于pre[i]的计算只与前一项的答案有关,因此我们可以不建立pre数组,直接用pre变量来记录
 * 		pre[i - 1]的答案
 * 
 * Code by java
 */

class Solution {
	public int subarraySum(int[] nums, int k) {
		int count = 0, pre = 0;
		HashMap<Integer, Integer> mp = new HashMap<>();
		mp.put(0, 1);
		for (int i = 0; i < nums.length; i++) {
			pre += nums[i];
			if (mp.containsKey(pre - k))
				count += mp.get(pre - k);
			mp.put(pre, mp.getOrDefault(pre, 0) + 1);
		}
		return count;
	}
}