Given an array of integers and an integer k, you need to find the number of consecutive subarrays in that array that sum to k.
Example 1:
Input: nums = [1,1,1], k = 2
Output: 2 , 1,1] and [1,1] are two different cases.
Note: The length of the array is [1, 20,000].
The range of elements in the array is [-1000, 1000] and the range of integer k is [-1e7, 1e7].
The intuitive approach to hash table prefixes and Ali Tencent bytes is to brute-force all the subarrays, and then calculate the sum separately, and if it is equal to k, the count is +1The time complexity of this practice is o(n 2),* which is as follows:
class solution: def subarraysum(self, nums: list[int], k: int) -int: cnt, n = 0, len(nums) for i in range(n): sum = 0 for j in range(i, n): sum += nums[j] if (sum == k): cnt += 1 return cnt
In fact, when I first saw this problem, I thought, "Is it possible to solve it with a sliding window?" ”。But I quickly gave up, because the range of terms in the array had negative values, which made it more complicated for us to expand or contract the window. The second idea is to prefix the sum, save the prefix sum of an array, and then use the difference method to derive the sum of arbitrary intervals, which is feasible, as follows:
class solution: def subarraysum(self, nums: list[int], k: int) -int: cnt, n = 0, len(nums) pre = [0] *n + 1) for i in range(1, n + 1): pre[i] = pre[i - 1] +nums[i - 1] for i in range(1, n + 1): for j in range(i, n + 1): if (pre[j] -pre[i - 1] == k): cnt += 1 return cnt
However, the question only asks for itTotalwithout having to find all the subarrays. Therefore, we can directly use the following algorithm with a time complexity of $o(n)$.
The core point of this approach is that the total number of subarrays found is actually equivalent to :
The number of subarrays ending in index 0The number of subarrays ending in index 1... The number of subarrays ending with index n - 1 and the number of subarrays ending with index i is equal to: the number of subarrays with prefix sum is acc - k, where acc is the current sum of prefixes. In order to be able to quickly extract the prefix and the number of acc - k, we can store it in a hash.
Specific algorithm: Maintain a hashmap, the key of the hashmap is the cumulative value acc, and the value is the number of occurrences of the cumulative value acc. Iterate over the array, and then keep updating the acc and hashmap, and if acc is equal to k, then it's obvious that +1If hashmap[acc - k] exists, we can add it to the result. The language is difficult to explain, so I drew a diagram to illustrate the case of nums = [1,2,3,3,0,3,4,2], k = 6.
As shown in the figure, when nums[3] is accessed, the hashmap is as shown in the figure, and the count is 2One of them is [1,2,3], which is easy to understand. The other one is [3,3].
This [3,3] is exactly what we get with hashmap[acc - k], i.e. hashmap[9 - 6].
Prefixes and can be used to avoid double counting by taking advantage of the sum of hashmap recordsLanguage support: js, pythonj**ascript code:
/* *lc app=leetcode id=560 lang=j**ascript * 560] subarray sum equals k *//** param nums * param k * return */var subarraysum = function (nums, k) ;let acc = 0; let count = 0; for (let i = 0; i < nums.length; i++)if (hashmap[acc] === void 0) else }return count;};
python code:
class solution: def subarraysum(self, nums: list[int], k: int) -int: d = {}acc = count = 0 for num in nums: acc += num if acc == k: count += 1 if acc - k in d: count += d[acc-k] if acc in d: d[acc] += 1 else: d[acc] = 1 return count