github repo 地址: https://github.com/GoldenaArcher/js_leetcode,Github 的目录 大概 会更新的更勤快一些。
题目地址:560. Subarray Sum Equals K
如下:
Given an array of integers
nums
and an integerk
, return the total number of subarrays whose sum equals tok
.A subarray is a contiguous non-empty sequence of elements within an array.
这个解法会超时,但是我觉得这个解法说的还是挺清楚的,还给了一个比较好的初始思路。
这种将所有的前置和存储在一个数组中,然后遍历两边前置去计算有多少个子数组。
以 [1, 2, 3]
为例,前置和数组的值为:[ 0, 1, 3, 6 ]
。
数组和的长度比数组多一个是当下标为 0 时,数组和自然为 0。
当下标为 1 时,当前值为 nums[0] + sums[0]
。
当下标为 2 时,,当前值为 nums[1] + sums[1]
。
以此类推。
总体上来说就是将所有的前置和相加,最后用进行双重遍历,找到 sums[i + j] - sums[i] === k
出现过多少次即可。
哈希表的解法一定程度上来说是 2 sum 的变种,2 sum 在 map 中获取的是 t a r g e t − n u m s [ i ] target - nums[i] target−nums[i] 存储的键值对是 ( n u m s [ i ] , i ) (nums[i], i) (nums[i],i),这里获取的则是 s u m − k sum - k sum−k,其中 s u m sum sum 为前数和,存储的键值对为 ( s u m , m a p . g e t ( s u m ) + 1 ) (sum, map.get(sum) + 1) (sum,map.get(sum)+1)。
依旧以官方题目中的 nums = [1, 2, 3], k = 3
为例:
初始化时
map 的值为: { ( 0 , 1 ) } \{(0, 1)\} {(0,1)},原因与暴力解中一样
当下标为 0 时
此时在 map 中搜索 s u m − k sum - k sum−k,即 -2。map 中并不包含这个值,继续下一步操作
map 的值为: { ( 0 , 1 ) , ( 1 , 1 ) } \{(0, 1), (1, 1)\} {(0,1),(1,1)}
此时下标为 1
此时在 map 中搜索 s u m − k sum - k sum−k,即 0, map 中可以取得 ( 0 , 1 ) (0, 1) (0,1),所以 counter += map.get(sum - k)
map 的值为: { ( 0 , 1 ) , ( 1 , 1 ) , ( 3 , 1 ) } \{(0, 1), (1, 1), (3, 1)\} {(0,1),(1,1),(3,1)}
找到 s u m − k sum - k sum−k 即代表当前子数组肯定能找到这样的一个组合,也就是 [1, 2]
此时下标为 2
此时在 map 中搜索 s u m − k sum - k sum−k,即 3, map 中可以取得 ( 3 , 1 ) (3, 1) (3,1),所以 counter += map.get(sum - k)
map 的值为: { ( 0 , 1 ) , ( 1 , 1 ) , ( 3 , 1 ) , ( 6 , 1 ) } \{(0, 1), (1, 1), (3, 1), (6, 1)\} {(0,1),(1,1),(3,1),(6,1)}
最终获得结果为 2.
关于关于出现包含不止一个子数组的情况,可以参考 nums = [1,-1,0], k = 0
这个案例。
初始化时
map 的值为: { ( 0 , 1 ) } \{(0, 1)\} {(0,1)}
当下标为 0
此时在 map 中搜索 s u m − k sum - k sum−k,即 -1。map 中并不包含这个值,继续下一步操作
map 的值为: { ( 0 , 1 ) , ( 1 , 1 ) } \{(0, 1), (1, 1)\} {(0,1),(1,1)}
当下标为 1
此时在 map 中搜索 s u m − k sum - k sum−k,为 0,map 中包含这个键,因此 counter += 1
map 的值为: { ( 0 , 2 ) , ( 1 , 1 ) } \{(0, 2), (1, 1)\} {(0,2),(1,1)}
当下标为 2
此时在 map 中搜索 s u m − k sum - k sum−k,为 0,map 中包含这个键,因此 counter += 1
注意,这里会出现 2 是因为有两个数组可以实现当前值:
[1, -1, 0]
[0]
map 的值为: { ( 0 , 3 ) , ( 1 , 1 ) } \{(0, 3), (1, 1)\} {(0,3),(1,1)}
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var subarraySum = function (nums, k) {
const n = nums.length;
const sums = new Array(n + 1).fill(0);
for (let i = 1; i <= n; i++) {
sums[i] = sums[i - 1] + nums[i - 1];
}
let counter = 0;
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
if (sums[j + 1] - sums[i] === k) counter++;
}
}
return counter;
};
var subarraySum = function (nums, k) {
const map = new Map([[0, 1]]);
let counter = 0,
sum = 0;
for (const num of nums) {
sum += num;
if (map.has(sum - k)) counter += map.get(sum - k);
if (map.has(sum)) map.set(sum, map.get(sum) + 1);
else map.set(sum, 1);
}
return counter;
};