力扣560(java&python)-和为k的子数组(中等)

题目:

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。

 示例 1:

输入:nums = [1,1,1], k = 2
输出:2
示例 2:

输入:nums = [1,2,3], k = 3
输出:2
 

提示:

1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subarray-sum-equals-k
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

前缀和+哈希表:

前缀和:表示nums的第0项到当前项的和。

  • 定义一个prefixSum数组,prefixSum[x]:第0项到第x项的和。prefixSum[x] = nums[0] + nums[1]+...+nums[x];
  • nums的某项 = 两个相邻前缀和之差:nums[x] = prefixSum[x] - prefixSum[x - 1]
  • nums的第 i 到 j 项的和:nums[i]+...+nums[j] = prefixSum[j] - prefixSum[i-1]
  • 当 i 为0时,此时i-1 = -1,故意让prefixSum[-1]为0,使得通式在i=0时也成立:nums[0] + ...+ nums[j] = prefixSum[j]

题目的意思就是求从第i 到 j项的子数组和等于k <==>有几种ij组合,满足prefixSum[j] -prefixSum[i -1] == k。

  • 不关心具体那两项的前缀和之差为k,只关心前缀和之差为k出现的次数;
  • 在遍历nums之前,故意让-1所对应的前缀和为0,这样通式在边界情况也成立,即在遍历之前,首先将前缀和为0 出现1次了 ==><0 : 1>放入map中;
  • 遍历nums,求每一项的前缀和,统计对应的出现次数,以键值对存入map;
  • 边存边查看map,如果map中存在key为【当前前缀和 - k】,说明之前出现的前缀和满足【当前前缀和 - key == k】,它出现的次数不断累加给count。

java代码:

 1 class Solution {
 2     public int subarraySum(int[] nums, int k) {
 3         Map<Integer, Integer> map = new HashMap<>();
 4         //先把边界<0, 1>:前缀和为0的次数加入到map中
 5         map.put(0,1);
 6         int presum = 0;
 7         int count = 0;
 8         //计算前缀和
 9         for(int num : nums){
10             presum += num;
11             //如果存在历史前缀和,则将次数统计到count中
12             if(map.containsKey(presum - k)){
13                 count += map.get(presum - k);
14             }
15             map.put(presum, map.getOrDefault(presum, 0) + 1);
16         }
17         return count;
18     }
19 }

 python3代码:

 1 class Solution:
 2     def subarraySum(self, nums: List[int], k: int) -> int:
 3         #当key不存在,默认为0
 4         map = collections.defaultdict(int)
 5         count = 0
 6         n = len(nums)
 7         presum = 0
 8         map[0] = 1
 9         for i in range(n):
10             presum += nums[i]
11 
12             count +=  map[presum - k]
13             map[presum] += 1
14         return count 

posted on 2022-10-17 10:42  我不想一直当菜鸟  阅读(23)  评论(0编辑  收藏  举报