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 个记录
相关推荐
All for pursuit.1 小时前
【回溯-3】39.组合总和
数据结构·c++·算法·leetcode
释厄6231 小时前
BSD 基础论——不要忘记连接·不要停滞循环·AI基础算法
人工智能·算法
yi0111 小时前
DAY19: LeetCode 28 找出字符串中第一个匹配项的下标
人工智能·笔记·python·算法·leetcode
不会就选b1 小时前
算法日常・每日刷题--<动态规划>6
数据结构·算法·leetcode
释厄6232 小时前
AI犯错即异质论——正确认知=免疫与安全防控技术算法
大数据·算法·安全
漂流瓶jz2 小时前
UVA-12545 比特变换器 题解答案代码 算法竞赛入门经典第二版
数据结构·算法·题解·aoapc·算法竞赛入门经典·uva·12545
积流成海2 小时前
哈希碰撞攻击全解析:从MD5到SHA1的安全演进史
算法·安全·哈希算法·哈希函数·盘子工具站·哈希计算
v:PLLucky202 小时前
眼部疾病智能检测系统
算法·yolo·机器学习·百度·facebook
Omics Pro2 小时前
00后大3休学创业!AI虚拟细胞
大数据·数据库·人工智能·算法·机器学习·自然语言处理