力扣——剑指 Offer II 010. 和为 k 的子数组(前缀和+哈希表)

题目(中等)

给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数。

示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2
解释: 此题 [1,1] 与 [1,1] 为两种不同的情况

示例 2 :
输入:nums = [1,2,3], k = 3
输出: 2

提示:

1 <= nums.length <= 2 * 10^4
-1000 <= nums[i] <= 1000
-10^7 <= k <= 10^7

思路

对于连续子数组的和,一定要想到前缀和,sum[i] - sum[j] 就是j到i的连续子数组之和;
下一步,找所有连续子数组之和等于k的个数,直观的想法用O(N^2)遍历,但看会超时;
那就换复杂度低的滑动窗口,但有负值,无法判断不等于k时窗口应该扩大还是缩小;
所以用哈希表,统计每种结果出现的次数。
需要满足sum[i] - sum[j] == k,也即sum[j] == sum[i] - k,对于i位置来说,之前的前缀和满足sum[i] - k的个数,即是到此为止的满足连续子数组和为k的个数,累加这个个数就是答案,并在统计后将新的sum[i]加入哈希表。
因为sum只用一次,其他都存到哈希表里了,可以只用一个变量压缩空间。

代码

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int n = nums.size();
        int sum = 0;
        int ans = 0;
        unordered_map<int, int> hash;
        hash[0] = 1;
        for(int i = 0; i < n; i++) {
            sum += nums[i];
            ans += hash[sum - k];
            hash[sum]++;
        }
        return ans;
    }
};

你可能感兴趣的:(算法,leetcode,算法,散列表,前缀和)