[LeetCode] 560. Subarray Sum Equals K

Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.

A subarray is a contiguous non-empty sequence of elements within an array.

Example 1:
Input: nums = [1,1,1], k = 2
Output: 2

Example 2:
Input: nums = [1,2,3], k = 3
Output: 2

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

和为 K 的子数组。

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

子数组是数组中元素的连续非空序列。

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

思路一 - 暴力解

题意是给一个数组和一个数字 K,请求出 input 数组中有多少个子数组的和为 K。两种做法,一种是暴力解;一种会用到 hashmap。

暴力解的思路是用两个 for loop 扫描 input 数组,扫描的时候记录累加和 sum,再用一个变量记录是否有满足条件的子数组满足 sum == k,若有就++。

复杂度

时间O(n^2)
空间O(1)

代码

JavaScript实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var subarraySum = function (nums, k) {
let res = 0;
for (let i = 0; i < nums.length; i++) {
let sum = 0;
for (let j = i; j < nums.length; j++) {
sum += nums[j];
if (sum === k) {
res++;
}
}
}
return res;
};

思路二 - 前缀和

用一个数组 sum 记录从 0 到 i 之间所有元素的累积总和。如果累积总和在索引 i 和索引 j 之间相差 k,即 sum[i] - sum[j] = k,则位于索引 i 和索引 j 之间的元素之和是 k。

根据这个思路,我们可以用 hashmap 记录数组所有的前 N 项的前缀和。key 是前缀和,value 是这个前缀和出现的次数。扫描的时候,如果 map 存在 sum(下图黄色部分) 和 sum - k(下图红色部分),就说明有满足条件的子数组,因为他们的差值是 k。同时因为数组可能存在负数的关系,加入前缀和的时候需要判断 key 是否存在过。举个例子,比如前 N 项的和是 sum,前 N-1 项的和是 sum - k,那么前 N 项的和 - 前 N-1 项的和 = K。

x, x, x, x, x, x, x, x - sum
x, x, x, x, x, x, x, k - sum - k

这个思路很好,能帮助解决很多求子数组,子区间的问题。

复杂度

时间O(n)
空间O(n)

代码

Java实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int subarraySum(int[] nums, int k) {
int res = 0;
int sum = 0;
// <unique的前缀和,这个前缀和出现了多少次>
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (map.containsKey(sum - k)) {
res += map.get(sum - k);
}
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
return res;
}
}

JavaScript实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var subarraySum = function (nums, k) {
// corner case
if (nums.length <= 0) return 0;

// normal case
let map = new Map([[0, 1]]);
let sum = 0;
let count = 0;
for (let i = 0; i < nums.length; i++) {
sum += nums[i];
if (map.has(sum - k)) {
count += map.get(sum - k);
}
if (!map.has(sum)) {
map.set(sum, 1);
} else {
map.set(sum, map.get(sum) + 1);
}
}
return count;
};

[LeetCode] 560. Subarray Sum Equals K
https://shurui91.github.io/posts/135141854.html
Author
Aaron Liu
Posted on
April 14, 2020
Licensed under