题目描述
思路解析动画文字版
记住「频次表去重 → 对每个 x 查 x+k 在不在」,下面每帧都在套它。本例 k=2 走 k>0 主线。
开局这排就是原数组,右边频次表还是空的。先逐个把元素记进频次表:同一个值再出现就把它的次数加一,这一步天然把重复值合并了。
扫到下标 0 的 3,第一次见,记进频次表 count[3] = 1。
扫到下标 1 的 1,第一次见,记进频次表 count[1] = 1。
扫到下标 2 的 4,第一次见,记进频次表 count[4] = 1。
又见到 1(下标 3),不新增一项,只把 count[1] 加到 2。重复值就这样被合并,后面只按「不同的值」来配对。
扫到下标 4 的 5,第一次见,记进频次表 count[5] = 1。
频次表建好,去重后只剩 4 个不同的值:1、3、4、5。k = 2 大于 0,接下来对每个不同的值 x,查 x + 2 在不在表里。
轮到值 1(绿色标出它在数组里的位置)。要凑差 2,它的搭档应该是 1 + 2 = 3。下一步去频次表里查 3 在不在。
拿着搭档 3 去频次表里翻:哈希查表是一步到位的 O(1) 操作,不用回头扫数组。看 3 这一项在不在表里。
频次表里有 3!于是 1 和 3 配成一对 (1, 3),答案加到 1。注意我们是按「不同的值」配的,所以哪怕 1 出现多次,这对也只算一次。
轮到值 3(绿色标出它在数组里的位置)。要凑差 2,它的搭档应该是 3 + 2 = 5。下一步去频次表里查 5 在不在。
拿着搭档 5 去频次表里翻:哈希查表是一步到位的 O(1) 操作,不用回头扫数组。看 5 这一项在不在表里。
频次表里有 5!于是 3 和 5 配成一对 (3, 5),答案加到 2。注意我们是按「不同的值」配的,所以哪怕 3 出现多次,这对也只算一次。
轮到值 4(绿色标出它在数组里的位置)。要凑差 2,它的搭档应该是 4 + 2 = 6。下一步去频次表里查 6 在不在。
拿着搭档 6 去频次表里翻:哈希查表是一步到位的 O(1) 操作,不用回头扫数组。看 6 这一项在不在表里。
频次表里没有 6,4 找不到差 2 的搭档,跳过它,答案不变,还是 2。
轮到值 5(绿色标出它在数组里的位置)。要凑差 2,它的搭档应该是 5 + 2 = 7。下一步去频次表里查 7 在不在。
拿着搭档 7 去频次表里翻:哈希查表是一步到位的 O(1) 操作,不用回头扫数组。看 7 这一项在不在表里。
频次表里没有 7,5 找不到差 2 的搭档,跳过它,答案不变,还是 2。
所有不同值都查完了,满足绝对差 2 的数对是 (1,3)、(3,5),一共 2 对,和开头说的一致。回头看:靠一张频次表去重 + 对每个 x 查一次 x + k,没有两两暴力,一遍线性就数完了。
边界都绕着「k=0 特判」和「按值去重」两件事。
两个高频追问:与两数之和的异同、k=0 为何特判。
参考代码
from typing import Listfrom collections import Counterclass Solution: def findPairs(self, nums: List[int], k: int) -> int: count = Counter(nums) if k == 0: return sum(v > 1 for v in count.values()) vals = set(count) return sum(1 for x in vals if x + k in vals)复杂度
- 时间:O(n),建频次表扫一遍 O(n);再遍历不超过 n 个不同值、每个查一次表 O(1),合起来 O(n)
- 空间:O(n),频次表最多存 n 个不同值
易错点
面试追问把动画讲成自己的话
追问这道题和「两数之和」有什么联系和区别?
追问k = 0 为什么要单独处理?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
有效三角形的个数
LeetCode 611 · 中等 · 沿着 双指针套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题