LeetCode560. 和为 K 的子数组(2024秋季每日一题 12)

给你一个整数数组 n u m s nums nums 和一个整数 k k k ,请你统计并返回 该数组中和为 k k k 的子数组的个数 。

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = 1,1,1, k = 2

输出:2

示例 2:

输入:nums = 1,2,3, k = 3

输出:2

提示:

1 < = n u m s . l e n g t h < = 2 ∗ 1 0 4 1 <= nums.length <= 2 * 10^4 1<=nums.length<=2∗104
− 1000 < = n u m s i < = 1000 -1000 <= numsi <= 1000 −1000<=numsi<=1000
− 1 0 7 < = k < = 1 0 7 -10^7 <= k <= 10^7 −107<=k<=107


思路:前缀和 + 哈希表

  • 先遍历一遍数组求出前缀和(为了防止越界检查,下标从 1 开始)
  • 对于前缀和,当 i+1\~j 这个区间的和为 k 时,则有 sj - si=k
  • 所以 求多少个 区间和为 k,就转换成了求有多少个(i,j)(j > i) sj - si= k
  • 如果暴力枚举(i,j)的话,需要 O ( N 2 ) O(N^2) O(N2) 的时间复杂度,可以考虑通过哈希表优化
  • 在哈希表中存储 sx 出现的个数,当遍历到当前元素时,只需要判断 (sj - k) 在哈希表是否存在,存在的话,在答案 res 上加上(sj - k)出现的次数(因为如果, sj - k 在 hash表中存在,那说明至少有一个 si 满足,sj - si == k,而sj - k 出现的次数,就是 对于当前 j,有多少个 i 满足,i\~j 区间的和为 k)

时间复杂度: O ( N ) O(N) O(N)

cpp 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        vector<int> s(nums.size() + 1, 0);
        for(int i = 1; i <= nums.size(); i++) s[i] += (s[i-1] + nums[i-1]);
        unordered_map<int, int> h;
        int res = 0;
        for(int i = 0; i <= nums.size(); i++){
            if(h.count(s[i] - k)) res += h[s[i] - k];
            h[s[i]] ++;
        }
        return res;
    }
};
相关推荐
To_OC1 小时前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
用户938515635076 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
To_OC7 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥8 小时前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程
地平线开发者9 小时前
Transformer模型部署之性能优化指南
算法
地平线开发者10 小时前
人在途中:从“编译失败”到“模型可落地”——CUDA 自定义算子
算法·自动驾驶
半个落月12 小时前
从递归到快速排序:用 JavaScript 把分治思想讲明白
javascript·算法·面试
小月土星13 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
javascript·算法·面试
小月土星13 小时前
JavaScript 递归入门:从 1 到 n 求和,再到数组扁平化
javascript·算法·面试