我们得到了一个整数数组和另一个数字k
,我们需要找到其总和等于k
的连续子数组的总数。我在LeetCode上找到了以下有趣的代码片段:
public class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0, sum = 0;
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))
count += map.get(sum - k);
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
return count;
}
}
我喜欢有效的解决方案,所以我试图理解它;但我有两个问题:
sum
及其frequency
存储在HashMap中的直觉是什么? 示例输入:[1,1,1]
和k = 2
;
输出:2
答案 0 :(得分:3)
在我们扫描nums[]
数组时,map
将包含我们看过特定sum
的次数(sum
表示从头开始对数字求和到目前为止)。
现在,在任何给定时间点if
,如果我们看到map
包含sum-k
X次,当前总和为sum
,我们就知道,我们发现了X个不同的子数组,其总和为k
。这是因为sum
包含从开头到当前点的总和,map
通过从开头到开始到某个点的总和来编制索引。如果map
包含大于1的值,则表示某个总和多次发生(如果num[]
为零或负数,则可能发生)。找到的子阵列来自于这个&#34;某些&#34;指向我们当前的位置,所以它必须是连续的。
答案 1 :(得分:1)
尼斯算法。
让我们从简单的事实开始:sum(1, i) = sum(1, j) + sum(j + 1, i)
(我这里不使用Java,这是通常的数学符号)
对于任何i
和j
都是如此。
我们需要找到所有sum(j+1, i)
等于k
。
找到sum(1, i) = sum(1, j) + k
或sum(1, i) -k = sum(1, j)
在您的计划中sum(1, i)
是sum
变量。因此,我们需要检查我们是否有j
为sum -k = sum(1, j)
为真。希望我们在sum(1, j)
中将所有map
作为键。
我们检查map.containsKey(sum - k)
,如果确实如此,则会有j
这样的 for (int num : nums) {
sum += num;
count += map.getOrDefault(sum - k, 0);
map.compute(sum, (key, value) -> (value == null) ? 1 : value + 1);
}
给我们所需的金额。
需要使用map中的值来计算获得此类总和的不同方式。
PS:BTW如果所有值都是非负值,则有更好的算法。它不需要额外的内存。
PPS:如果您使用Java 8,我也会对您的代码进行一些改进
{{1}}
答案 2 :(得分:0)
3个关键事项:
count
已在地图中时,sum - k
我将其分为3个案例:
1st:数字大于零。
每个键的频率等于1
那么计数增加了多少?只有当密钥已经存在于地图中时,它才会增加。
钥匙都是以前的总和。因此条件if (map.containsKey(sum - k))
的当前关键字是sum - k
。如果sum - k
是一个关键字,则意味着之前的总和(sum - k
)和当前总和之间是和,等于k
的元素(原因k + (sum - k) = sum
- 我们当前的值) 。所以我们可以增加count
- 我们找到了子数组。
第二名:数字大于等于零。
所以现在我们可以在它们之间放置零。它没有多大区别,但您可以想象如果我们增加count
会发生什么,在下一步中我们的nums
数组中会有0。
在这种情况下,我们会再次增加count
。
包含零,我们的频率会发生变化。想象一下这个例子:
subarraySum({0, 0, 0, 7, 0}, 7);
结果为8。
请记住,第一个键是0.所以当我们迭代时,我们在7,我们有一个地图(0: 4)
。现在sum = 7
和7 - 7 = 0
,我们有3个,所以这个时间计数增加了这个频率。现在我们从数组中选取最后一个元素 - 0。此键的值仍为4. sum - k
仍然相同,所以我们的count
再次增加了4。
第3名:整数。
我认为你明白了这一点;)这次负数也可能增加一些频率。
如果我们在地图中有关键sum - key
,则表示在之前的总和(sum - k
)之间,现在我们有了整数,总计为k
(导致k + (sum - k) = sum
- 我们的当前值)。如果是这样,让我们按频率增加计数。