题目描述
思路解析动画文字版
记住「前缀和取余,余数重复且间距≥2 即命中;哈希存最早下标」,下面每帧都在套它。
开局先放一条「余数 0 → 下标 −1」:代表「什么都不取」的空前缀。这样从下标 0 开始的整段也能被正确匹配。
扫到下标 0(值 2),更新前缀和并对 11 取余,得到余数 2。拿它去哈希表查:之前出现过吗?
余数 2 是第一次见,把「余数 2 → 最早下标 0」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 1(值 3),更新前缀和并对 11 取余,得到余数 5。拿它去哈希表查:之前出现过吗?
余数 5 是第一次见,把「余数 5 → 最早下标 1」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 2(值 4),更新前缀和并对 11 取余,得到余数 9。拿它去哈希表查:之前出现过吗?
余数 9 是第一次见,把「余数 9 → 最早下标 2」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 3(值 5),更新前缀和并对 11 取余,得到余数 3。拿它去哈希表查:之前出现过吗?
余数 3 是第一次见,把「余数 3 → 最早下标 3」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 4(值 4),更新前缀和并对 11 取余,得到余数 7。拿它去哈希表查:之前出现过吗?
余数 7 是第一次见,把「余数 7 → 最早下标 4」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 5(值 5),更新前缀和并对 11 取余,得到余数 1。拿它去哈希表查:之前出现过吗?
余数 1 是第一次见,把「余数 1 → 最早下标 5」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 6(值 7),更新前缀和并对 11 取余,得到余数 8。拿它去哈希表查:之前出现过吗?
余数 8 是第一次见,把「余数 8 → 最早下标 6」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 7(值 7),更新前缀和并对 11 取余,得到余数 4。拿它去哈希表查:之前出现过吗?
余数 4 是第一次见,把「余数 4 → 最早下标 7」存进哈希表(只存最早的,后面才好凑长间距)。继续下一个。
扫到下标 8(值 9),更新前缀和并对 11 取余,得到余数 2。拿它去哈希表查:之前出现过吗?
余数 2 之前在下标 0 出现过,间距 8 ≥ 2,它们之间这段(绿色)前缀和之差正好是 11 的倍数,找到了!返回 true。
绿色这段(下标 1..8,3+4+5+4+5+7+7+9 = 44)的和是 11 的倍数,长度 ≥ 2,所以答案 true。本质就是「两处前缀和余数相同」。
边界先想清:两个 0、单元素、刚好凑成 k。
面试常追问 k=0 变体与取余的双重作用。
参考代码
from typing import Listclass Solution: def checkSubarraySum(self, nums: List[int], k: int) -> bool: first = {0: -1} prefix = 0 for i, x in enumerate(nums): prefix = (prefix + x) % k if prefix in first: if i - first[prefix] >= 2: return True else: first[prefix] = i return False复杂度
- 时间:O(n),扫一遍,哈希查/存 O(1)
- 空间:O(min(n,k)),哈希最多存 k 种余数
易错点
面试追问把动画讲成自己的话
追问如果 k 可能为 0 怎么办?
追问为什么取余能防止前缀和溢出?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
连续数组
LeetCode 525 · 中等 · 沿着 前缀和套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题