560. 和为K的子数组
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
解题思路: 本题一开始以为是用滑动窗口解题,但是在写代码的时候发现,整数数组的值有正有负,和值也不是单调的,因此窗口的收缩方向不好判断,于是换了种思路。此题的背景是求和,而且是求序列的连续子集和,那么为了降低时间复杂度,往往我们会将0到当前索引位置的和值求出来放在一个和值数组中,然后求某段子数组的和值,比如[i,j],只需计算SUM[i,j]=sum[j]-sum[i]+num[i],但是算法的时间复杂度为
O
(
N
2
)
O(N^2)
O(N2),好像至此,OJ也能通过这个解法。然后看了grandyang的解法,再结合本题给出的标签,哈希,题目认为的最优解法是哈希解法。
哈希解题思路:我们可以分析下面这个图,这段序列取自给定数组nums,左边界是nums的左边界,右边界是nums中间某个点,我们分析这个当前状态,我们的和值k是有中间某段连续序列组成,因此我们依然在遍历的过程中将当前位置到0-index点的和值求出来,但是我们不用保存在一个数组,仅仅维护一个到当前位置的和值sum即可,在遍历的过程中,我们将这个和值与它出现的个数用哈希映射起来,那么当我们遍历到图中这个状态时,我们要判断和值k是否存在,只需判断和值sum-k是否存在,顺着这个思路,此题可解。
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int res = 0, sum = 0, n = nums.size();
unordered_map<int, int> m{{0,1}};
for (int i = 0; i < n; ++i) {
sum += nums[i];
res += m[sum - k];
++m[sum];
}
return res;
}
};
总结
对连续求和值的题做一个简单的总结和回顾。连续和值的解法一般用和值数组即可降低一个维度的时间复杂度,这是通常解法,若涉及到判断和值个数的问题,比如这题,那么需要想到用哈希来记录值和个数的映射,这个直接想比较难想到,但是另一个想法我们是很常见的,即,当我们需要判断或者找寻的和值为k时,若已知我们当前位置到某个位置(常规是起点0-index)的和值,那我们只需要判断或者找寻从起点位置到某个位置的和值为sum-k的序列,就可以解决和值为k的问题了。
参考资料
https://www.cnblogs.com/grandyang/p/6810361.html