Skip to content

Commit b71bd3c

Browse files
author
lucifer
committed
2 parents a51a52d + 082bb1f commit b71bd3c

File tree

4 files changed

+174
-25
lines changed

4 files changed

+174
-25
lines changed

README.en.md

Lines changed: 8 additions & 7 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)
@@ -246,14 +247,14 @@ The data structures mainly include:
246247

247248
### Summary of Data Structures and Algorithm
248249

249-
- [Data Structure](./thinkings/basic-data-structure-en.md) (Drafts)
250-
- [Basic Algorithm](./thinkings/basic-algorithm-en.md)(Drafts)
250+
- [Data Structure](./thinkings/basic-data-structure-en.md)
251+
- [Basic Algorithm](./thinkings/basic-algorithm-en.md)
251252
- [Binary Tree Traversal](./thinkings/binary-tree-traversal.en.md)
252-
- [Dynamic Programming](./thinkings/dynamic-programming-en.md)
253-
- [Huffman Encode and Run Length Encode](./thinkings/run-length-encode-and-huffman-encode-en.md)
254-
- [Bloom Filter](./thinkings/bloom-filter-en.md)
255-
- [String Problems](./thinkings/string-problems-en.md)
256-
- [Sliding Window Technique](./thinkings/slide-window.en.md)
253+
- [Dynamic Programming](./thinkings/dynamic-programming-en.md)
254+
- [Huffman Encode and Run Length Encode](./thinkings/run-length-encode-and-huffman-encode-en.md)
255+
- [Bloom Filter](./thinkings/bloom-filter-en.md)
256+
- [String Problems](./thinkings/string-problems-en.md)
257+
- [Sliding Window Technique](./thinkings/slide-window.en.md)
257258

258259
### Anki Flashcards
259260

problems/152.maximum-product-subarray.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,26 @@
33
https://leetcode.com/problems/maximum-product-subarray/description/
44

55
## 题目描述
6-
76
```
8-
Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.
7+
给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
98
10-
Example 1:
9+
 
1110
12-
Input: [2,3,-2,4]
13-
Output: 6
14-
Explanation: [2,3] has the largest product 6.
15-
Example 2:
11+
示例 1:
1612
17-
Input: [-2,0,-1]
18-
Output: 0
19-
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
13+
输入: [2,3,-2,4]
14+
输出: 6
15+
解释: 子数组 [2,3] 有最大乘积 6。
16+
示例 2:
2017
18+
输入: [-2,0,-1]
19+
输出: 0
20+
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
2121
```
2222

2323
## 思路
2424

25-
> 这道题目的通过率非常低
26-
27-
这道题目要我们求解连续的 n 个数中乘积最大的积是多少。这里提到了连续,笔者首先
28-
想到的就是滑动窗口,但是这里比较特殊,我们不能仅仅维护一个最大值,因此最小值(比如-20)乘以一个比较小的数(比如-10)
25+
这道题目要我们求解连续的 n 个数中乘积最大的积是多少。这里提到了连续,笔者首先想到的就是滑动窗口,但是这里比较特殊,我们不能仅仅维护一个最大值,因此最小值(比如-20)乘以一个比较小的数(比如-10)
2926
可能就会很大。 因此这种思路并不方便。
3027

3128
首先来暴力求解,我们使用两层循环来枚举所有可能项,这种解法的时间复杂度是O(n^2), 代码如下:
@@ -36,7 +33,6 @@ var maxProduct = function(nums) {
3633
let temp = null;
3734
for (let i = 0; i < nums.length; i++) {
3835
temp = nums[i];
39-
max = Math.max(temp, max);
4036
for (let j = i + 1; j < nums.length; j++) {
4137
temp *= nums[j];
4238
max = Math.max(temp, max);
@@ -47,9 +43,11 @@ var maxProduct = function(nums) {
4743
};
4844
```
4945

50-
因此我们需要同时记录乘积最大值和乘积最小值,然后比较元素和这两个的乘积,去不断更新最大值。
5146

52-
![](https://tva1.sinaimg.cn/large/0082zybply1gcatuvun39j30gr08kt9l.jpg)
47+
48+
前面说了`最小值(比如-20)乘以一个比较小的数(比如-10)可能就会很大` 。因此我们需要同时记录乘积最大值和乘积最小值,然后比较元素和这两个的乘积,去不断更新最大值。当然,我们也可以选择只取当前元素。因此实际上我们的选择有三种,而如何选择就取决于哪个选择带来的价值最大(乘积最大或者最小)。
49+
50+
![](https://pic.leetcode-cn.com/7d39989d10d982d44cbd6b6f693cf5171865c0654f7c3754e27ec1afc2c0de5d.jpg)
5351

5452
这种思路的解法由于只需要遍历一次,其时间复杂度是O(n),代码见下方代码区。
5553

@@ -137,3 +135,7 @@ var maxProduct = function(nums) {
137135
**复杂度分析**
138136
- 时间复杂度:$O(N)$
139137
- 空间复杂度:$O(1)$
138+
139+
更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经30K star啦。
140+
141+
大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解
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).

thinkings/slide-window.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,4 @@ Some problems here are intuitive that you know the sliding window technique woul
8484

8585
## Further Readings
8686

87-
- [LeetCode Sliding Window Series Discussion](https://leetcode.com/problems/binary-subarrays-with-sum/discuss/186683/)
87+
- [LeetCode Sliding Window Series Discussion](https://leetcode.com/problems/binary-subarrays-with-sum/discuss/186683/)(English)

0 commit comments

Comments
 (0)