LeetCode 热题 100——子串——和为 K 的子数组

10.和为 K 的子数组

题目描述

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

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

示例 1:

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

输出:2

示例 2:

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

输出:2

提示:

1 <= nums.length <= 2 * 104

-1000 <= nums[i] <= 1000

-107 <= k <= 107

求解

(1)暴力求解

遍历所有可能。一开始,还想着排序,不过排序就乱了。。。

js 复制代码
var subarraySum = function(nums, k) {
    if (nums.length === 0) return 0
    let ans = 0;
    for (let i = 0; i < nums.length; i++) {
        // 单个数字
        if (nums[i] === k) ans++
        let item = nums[i]
        for (let j = i + 1; j < nums.length; j++) {
            item += nums[j]
            if (item === k) {
                ans ++
            }
        }
    }
    return ans
};

(2)优化:前缀和 + 哈希表

  • 什么是前缀和?

    定义一个前缀和数组 prefixSum,其中 prefixSum[i] 表示数组 nums 中前 i 个元素的和(即 nums[0] 到 nums[i-1] 的和)

    js 复制代码
    prefixSum[0] = 0 (前 0 个元素的和,也就是没有元素的和)
    prefixSum[1] = nums[0]
    prefixSum[2] = nums[0] + nums[1]
    prefixSum[3] = nums[0] + nums[1] + nums[2]
    ...
    prefixSum[n] = nums[0] + nums[1] + ... + nums[n-1]

    那么,数组中从索引 j 到 i-1 的子数组(即 nums[j], nums[j+1], ..., nums[i-1])的和就可以表示为:sum(nums[j..i-1]) = prefixSum[i] - prefixSum[j]

  • 问题转化

    我们的目标是找到所有满足 sum(nums[j..i-1]) = k 的子数组。根据上面的公式,这等价于找到所有满足 prefixSum[i] - prefixSum[j] = k 的 (i, j) 对。

    我们可以将其变形为:prefixSum[j] = prefixSum[i] - k

    思路就变成了:当我们遍历到第 i 个元素,计算出 prefixSum[i] 时,我们想知道在 i 之前,有多少个 j 满足 prefixSum[j] 的值等于 prefixSum[i] - k。每找到一个这样的 j,就意味着存在一个以当前 i-1 为结尾的子数组,其和为 k

  • 哈希表的作用

    为了高效地回答 "之前有多少个 prefixSum[j] 等于某个值" 这个问题,我们可以使用一个哈希表(在 JavaScript 中是 Map 或普通对象)。

    • 键 (Key):我们遍历过程中遇到的 prefixSum 值。
    • 值 (Value):该 prefixSum 值出现的次数。

具体代码:

js 复制代码
var subarraySum = function(nums, k) {
    if (nums.length === 0) return 0
    let ans = 0
    let preSum = 0
    let map = new Map() // 存放 前缀和 出现的次数
    map.set(0, 1) // 空集
    for (let num of nums) {
        preSum += num // 求前缀和
        // 判断 是否有 符合条件的,有则将前缀和加起来
        if (map.has(preSum - k)) ans += map.get(preSum - k)
        // 将当前前缀和加入
        map.set(preSum, (map.get(preSum) || 0) + 1)
    }
    return ans
};
相关推荐
CoovallyAIHub2 小时前
VisionClaw:智能眼镜 + Gemini + Agent,看一眼就能帮你搜、帮你发、帮你做
算法·架构·github
CoovallyAIHub2 小时前
低空安全刚需!西工大UAV-DETR反无人机小目标检测,参数减少40%,mAP50:95提升6.6个百分点
算法·架构·github
CoovallyAIHub2 小时前
IEEE Sensors | 湖南大学提出KGP-YOLO:先定位风电叶片再检测缺陷,三数据集mAP均超87%
算法
Yupureki3 小时前
《算法竞赛从入门到国奖》算法基础:动态规划-路径dp
数据结构·c++·算法·动态规划
副露のmagic3 小时前
数组章节 leetcode 思路&实现
算法·leetcode·职场和发展
荣光属于凯撒3 小时前
P2176 [USACO11DEC] RoadBlock S / [USACO14FEB] Roadblock G/S
算法·图论
雨季mo浅忆4 小时前
记录利用Cursor快速实现拖拽式问卷题型创建
算法
酉鬼女又兒4 小时前
零基础快速入门前端Web存储(sessionStorage & localStorage)知识点详解与蓝桥杯考点应用(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·html
Yzzz-F4 小时前
2018-2019 ACM-ICPC, Asia Dhaka Regional ContestC[数论]
算法
Frostnova丶4 小时前
LeetCode 3474. 字典序最小的生成字符串
算法·leetcode·职场和发展