题目:和为 K 的子数组

解法一:暴力解法

使用双层循环,每次从当前位置向后遍历,直到总和等于目标值(res加一)

subarraySum()

 1int subarraySum(vector<int>& nums, int k)
 2{
 3    int n = nums.size();
 4    int res = 0;
 5    for(int i = 0; i < n; i++)
 6    {
 7        int sum = 0;
 8        for(int j = i; j < n; j++)
 9        {
10            sum += nums[j];
11            if(sum == k)
12            {
13                res++;
14                continue;
15            }
16        }
17    }
18    return res;
19}

解法二:前缀和

思路:使用一张哈希表记录之前出现的和以及对应的次数,当前连续子序列长度为sum(从头一直加到尾),如果能够在第 j 个元素的位置,找到在前 j 个元素中,和为 sum - k 的连续子数组,那么从 j 到 i 的这段子数组的和就一定等于 k (k = sum - (sum - k))

更简单的理解是:使用哈希表记录每个元素的前缀和,并统计所有相同前缀和的出现次数;当我们遍历到第 j 个元素时,此时需要查找在【0,j】范围内,是否存在子数组之和为 k——等价于在【0,j - 1】范围内,是否存在子数组之和为 sum - k,因为我们已经直到以 j 为结尾的前缀和为 sum,只需要减去 (sum - k),所得到的子数组之和就为 k

subarraySum()

 1int subarraySum(vector<int>& nums, int k)
 2{
 3    std::unordered_map<int, int> prefixCount;
 4    prefixCount[0] = 1;
 5
 6    int res = 0, sum = 0;
 7    for(auto num : nums)
 8    {
 9        sum += num;
10        if(prefixCount.count(sum - k))
11        {
12            res += prefixCount[sum - k];
13        }
14        prefixCount[sum]++;
15    }
16    return res;
17}

原文:medium