LeetCode-560.和为 K 的子数组

误区:为什么不能直接用滑动窗口?

很多做过子数组滑动窗口题的同学第一反应就是双指针滑动窗口。

✅ 滑动窗口适用前提:数组全部都是正数。窗口扩大总和一定变大,窗口缩小总和一定变小,存在单调性。

本题数组里面可以包含负数和 0!

一旦存在负数,向右扩大右边界,总和反而有可能变小;向左移动左边界,总和反而变大。总和不再单调递增,左右指针没有办法按照规则收缩窗口,滑动窗口失效,不能使用。


基础概念:前缀和

定义前缀和数组 preSum:

preSum[i]:数组前 i 个元素的累加和(nums[0] ~ nums[i‑1])

(preSum0=0

preSum1=nums0

preSum2=nums0+nums1

preSumi = sum_{x=0}^{i-1} numsx)区间 nums[j ... i‑1](下标 j 到 i‑1 的连续子数组)的和等于:

(preSumi - preSumj = k)

移项变形得到:

含义:当我们遍历到位置i,当前前缀和是preSum[i];我们希望统计历史上有多少个前缀和的值正好等于 preSum[i]‑k,每出现一次就代表找到了一段子数组,它的和等于 k。

算法思路(前缀和 + 哈希优化)

Python 完整代码

复制代码
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        cnt=defaultdict(int)
        ans=s=0 #s为前缀和
        for x in nums:
            cnt[s]+=1
            s+=x
            ans+=cnt[s-k]
        return ans

复杂度分析

  • 时间复杂度:(O(n)),只遍历数组一遍,哈希表查询插入都是 O (1)
  • 空间复杂度:(O(n)),最坏情况所有前缀和各不相同,哈希表保存 n 个记录
相关推荐
Navigator_Z1 小时前
LeetCode //C - 1301. Number of Paths with Max Score
c语言·算法·leetcode
卡卡~~1 小时前
“101计划”核心课程实践教材《数据实验结构指导-C++语言版》题目集
开发语言·c++·学习·算法
企业数字化笔记2 小时前
AI视频增强后画质怎么验收?插值基线、伪细节与帧间闪烁的检查方法
人工智能·算法·音视频
学逆向的2 小时前
C 内存属性
c语言·开发语言·算法·网络安全
lengxuenong3 小时前
树状数组 · 信息学学习手册1-求和3个模板
c++·学习·算法·青少年编程
ComputerInBook3 小时前
泛函分析概观
人工智能·算法·机器学习·泛函分析
Nuanyt3 小时前
LeetCode Hot100 刷题笔记 · 普通数组专题
java·笔记·算法·leetcode
q27551300423 小时前
AS8132 DP转HDMI 4K60(420)被动式 国产性价比AS方案
linux·算法·硬件架构·dash
安全指北针3 小时前
密态计算:数据 “可用不可见” 的底层技术解析
人工智能·算法