Skip to content

Commit 95aa868

Browse files
authored
feat(translation): azl397985856#364 translate problem 560 (azl397985856#366)
1 parent e5811ce commit 95aa868

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

README.en.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ The data structures mainly include:
217217
- [0516.longest-palindromic-subsequence](./problems/516.longest-palindromic-subsequence.md)
218218
- [0518.coin-change-2](./problems/518.coin-change-2.md)
219219
- [0547.friend-circles](./problems/547.friend-circles-en.md) 🆕✅
220+
- [0560.subarray-sum-equals-k](./problems/560.subarray-sum-equals-k.en.md)
220221
- [0609.find-duplicate-file-in-system](./problems/609.find-duplicate-file-in-system.md)
221222
- [0875.koko-eating-bananas](./problems/875.koko-eating-bananas.md)
222223
- [0877.stone-game](./problems/877.stone-game.md)
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
## Problem
2+
3+
https://leetcode.com/problems/subarray-sum-equals-k/description/
4+
5+
## Problem Description
6+
7+
```
8+
Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.
9+
10+
Example 1:
11+
Input:nums = [1,1,1], k = 2
12+
Output: 2
13+
Note:
14+
The length of the array is in range [1, 20,000].
15+
The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].
16+
```
17+
18+
## Solution
19+
20+
The simplest method is `Brute-force`. Consider every possible subarray, find the sum of the elements of each of those subarrays and check for the equality of the sum with `k`. Whenever the sum equals `k`, we increment the `count`. Time Complexity is O(n^2). Implementation is as followed.
21+
22+
```py
23+
class Solution:
24+
def subarraySum(self, nums: List[int], k: int) -> int:
25+
cnt, n = 0, len(nums)
26+
for i in range(n):
27+
for j in range(i, n):
28+
if (sum(nums[i:j + 1]) == k): cnt += 1
29+
return cnt
30+
```
31+
32+
If we implement the `sum()` method on our own, we get the time of complexity O(n^3).
33+
34+
```py
35+
class Solution:
36+
def subarraySum(self, nums: List[int], k: int) -> int:
37+
cnt, n = 0, len(nums)
38+
for i in range(n):
39+
for j in range(i, n):
40+
sum = 0
41+
for x in range(i, j + 1):
42+
sum += nums[x]
43+
if (sum == k): cnt += 1
44+
return cnt
45+
```
46+
47+
At first glance I think "maybe it can be solved by using the sliding window technique". However, I give that thought up when I find out that the given array may contain negative numbers, which makes it more complicated to expand or narrow the range of the sliding window. Then I think about using a prefix sum array, with which we can obtain the sum of the elements between every two indices by subtracting the prefix sum corresponding to the two indices. It sounds feasible, so I implement it as followed.
48+
49+
```py
50+
class Solution:
51+
def subarraySum(self, nums: List[int], k: int) -> int:
52+
cnt, n = 0, len(nums)
53+
pre = [0] * (n + 1)
54+
for i in range(1, n + 1):
55+
pre[i] = pre[i - 1] + nums[i - 1]
56+
for i in range(1, n + 1):
57+
for j in range(i, n + 1):
58+
if (pre[j] - pre[i - 1] == k): cnt += 1
59+
return cnt
60+
```
61+
62+
Actually, there is a more clever way to do this. Instead of using a prefix sum array, we use a hashmap to reduce the time complexity to O(n).
63+
64+
Algorithm:
65+
66+
- We make use of a hashmap to store the cumulative sum `acc` and the number of times the same sum occurs. We use `acc` as the `key` of the hashmap and the number of times the same `acc` occurs as the `value`.
67+
68+
- We traverse over the given array and keep on finding the cumulative sum `acc`. Every time we encounter a new `acc` we add a new entry to the hashmap. If the same `acc` occurs, we increment the count corresponding to that `acc` in the hashmap. If `acc` equals `k`, obviously `count` should be incremented. If `acc - k` got, we should increment `account` by `hashmap[acc - k]`.
69+
70+
- The idea behind this is that if the cumulative sum upto two indices is the same, the sum of the elements between those two indices is zero. So if the cumulative sum upto two indices is at a different of `k`, the sum of the elements between those indices is `k`. As `hashmap[acc - k]` keeps track of the number of times a subarray with sum `acc - k` has occured upto the current index, by doing a simple substraction `acc - (acc - k)` we can see that `hashmap[acc - k]` actually also determines the number of times a subarray with sum `k` has occured upto the current index. So we increment the `count` by `hashmap[acc - k]`.
71+
72+
Here is a graph demonstrating this algorithm in the case of `nums = [1,2,3,3,0,3,4,2], k = 6`.
73+
74+
![560.subarray-sum-equals-k](../assets/problems/560.subarray-sum-equals-k.jpg)
75+
76+
When we are at `nums[3]`, the hashmap is as the picture shows, and `count` is 2 by this time. `[1, 2, 3]` accounts for one of the count, and `[3, 3]` accounts for another.
77+
78+
The subarray `[3, 3]` is obtained from `hashmap[acc - k]`, which is `hashmap[9 - 6]`.
79+
80+
## Key Points
81+
82+
- Prefix sum array
83+
- Make use of a hashmap to track cumulative sum and avoid repetitive calculation.
84+
85+
## Code (`JavaScript/Python`)
86+
87+
*JavaScript Code*
88+
```js
89+
/*
90+
* @lc app=leetcode id=560 lang=javascript
91+
*
92+
* [560] Subarray Sum Equals K
93+
*/
94+
/**
95+
* @param {number[]} nums
96+
* @param {number} k
97+
* @return {number}
98+
*/
99+
var subarraySum = function (nums, k) {
100+
const hashmap = {};
101+
let acc = 0;
102+
let count = 0;
103+
104+
for (let i = 0; i < nums.length; i++) {
105+
acc += nums[i];
106+
107+
if (acc === k) count++;
108+
109+
if (hashmap[acc - k] !== void 0) {
110+
count += hashmap[acc - k];
111+
}
112+
113+
if (hashmap[acc] === void 0) {
114+
hashmap[acc] = 1;
115+
} else {
116+
hashmap[acc] += 1;
117+
}
118+
}
119+
120+
return count;
121+
};
122+
```
123+
124+
*Python Cose*
125+
126+
```py
127+
class Solution:
128+
def subarraySum(self, nums: List[int], k: int) -> int:
129+
d = {}
130+
acc = count = 0
131+
for num in nums:
132+
acc += num
133+
if acc == k:
134+
count += 1
135+
if acc - k in d:
136+
count += d[acc-k]
137+
if acc in d:
138+
d[acc] += 1
139+
else:
140+
d[acc] = 1
141+
return count
142+
```
143+
144+
## Extension
145+
146+
There is a similar but a bit more complicated problem. Link to the problem: [437.path-sum-iii](https://github.com/azl397985856/leetcode/blob/master/problems/437.path-sum-iii.md)(Chinese).

0 commit comments

Comments
 (0)