← 返回编程题库
coding-subarray-sum-equals-k中等免费版2000ms未尝试

和为 K 的子数组数

Subarray Sum Equals K

开始编码

策略组在复盘一支长长的日 PnL 序列 nums,想数出有多少个连续交易窗口的累计收益恰好等于目标值 k。形式化:对多少对下标 (l, r)(满足 0 ≤ l ≤ r < n)有 nums[l] + nums[l+1] + ... + nums[r] = k?每一个这样的窗口就是历史上一次「连续若干天累计收益正好命中目标」的事件。要求在 n = 10⁴ 量级、且数组里可能含负数(回撤日)和零(平盘日)的输入上跑得够快。

请实现 solution(nums: list[int], k: int) -> int。返回连续子数组和等于 k 的个数。空子数组不算;不同起止位置即使数值内容相同也分别计数。

示例 1solution([1, 1, 1], 2) 返回 2。两个合法窗口是 nums[0..1]nums[1..2]示例 2solution([1, 2, 3], 3) 返回 2——单元素 [3] 与连续两个 [1, 2]示例 3solution([0, 0, 0], 0) 返回 6——所有 l ≤ r 的 (l, r) 都合法:(0,0), (0,1), (0,2), (1,1), (1,2), (2,2),共 3*4/2 = 6 个。

朴素双重循环是 O(n²),n = 10⁴ 时约 10⁸ 次加法,时间不够。前缀和 + 哈希表这个套路把它降到 O(n):令 P[i] = nums[0] + ... + nums[i-1],任意子数组之和是 P[r+1] - P[l],需要找的就是 P[r+1] - P[l] = k 的下标对。从左到右扫,维护当前运行和 s 与一个记录每种前缀和出现次数的哈希表 counts(初始 counts[0] = 1,代表空前缀)。每一步先把 counts.get(s - k, 0) 累加进答案,再把 counts[s] += 1。负数和零都能统一处理,因为我们没有假设前缀和单调——这里不能用滑动窗口。

约束条件

  • 0 ≤ len(nums) ≤ 10000
  • -10⁷ ≤ nums[i] ≤ 10⁷
  • -10⁷ ≤ k ≤ 10⁷
  • 空输入返回 0
  • 返回值是精确整数计数(不需要浮点容差)

样例

Case 1 · classic three ones, k=2

输入: [[1,1,1],2]

期望: 2

两个合法窗口:nums[0..1] = [1,1] 与 nums[1..2] = [1,1],都求和为 2。它们起止下标不同,所以分别计数。

Case 2 · 1,2,3 with k=3

输入: [[1,2,3],3]

期望: 2

两个合法窗口:单元素 [3](即 nums[2..2])和连续两个 [1,2](即 nums[0..1]),各求和为 3。

Case 3 · all zeros with k=0 — triangular count

输入: [[0,0,0],0]

期望: 6

全 0 数组、k=0 时所有 l ≤ r 的 (l, r) 对都合法。N=3 时共 N*(N+1)/2 = 6 个。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · classic three ones, k=2

输入: [[1,1,1],2]

期望: 2

两个合法窗口:nums[0..1] = [1,1] 与 nums[1..2] = [1,1],都求和为 2。它们起止下标不同,所以分别计数。

Case 2 · 1,2,3 with k=3

输入: [[1,2,3],3]

期望: 2

两个合法窗口:单元素 [3](即 nums[2..2])和连续两个 [1,2](即 nums[0..1]),各求和为 3。

Case 3 · all zeros with k=0 — triangular count

输入: [[0,0,0],0]

期望: 6

全 0 数组、k=0 时所有 l ≤ r 的 (l, r) 对都合法。N=3 时共 N*(N+1)/2 = 6 个。