当前位置: 首页 > news >正文

​从454. 四数相加 II 中学到Counter​

从454. 四数相加 II 中学到Counter,我们使用哈希表(Counter将时间复杂度从暴力的 (O(n^4)) 优化到 (O(n^2))。


一、Counter的内部数据结构

Counter是什么?

  • Counter是 Python 标准库collections模块中的一个字典子类(dict subclass)
  • 它专门用于计数可哈希对象
  • 底层实现就是哈希表(hash table),和普通dict一样,基于开放寻址或链地址法(CPython 中是开放寻址)。

🔧 内部结构示例

from collections import Counter cnt = Counter(['a', 'b', 'a', 'c', 'b', 'a']) print(cnt) # 输出: Counter({'a': 3, 'b': 2, 'c': 1})

其内部存储等价于:

{'a': 3, 'b': 2, 'c': 1}
  • 键(key):元素(必须可哈希,如 int、str、tuple)
  • 值(value):该元素出现的次数(int)

💡 所以Counter插入、查询、更新操作平均时间复杂度都是O(1)


二、code 中Counter的实例分析

cnt = Counter(x + y for x in nums1 for y in nums2)

📌 这行做了什么?

  • 遍历nums1nums2的所有组合(共 (n^2) 对)
  • 计算每对的和s = x + y
  • 统计每个和s出现的次数

🧪 举个具体例子

假设:

nums1 = [1, 2] nums2 = [-2, -1]

那么x + y的所有可能为:

  • 1 + (-2) = -1
  • 1 + (-1) = 0
  • 2 + (-2) = 0
  • 2 + (-1) = 1

所以:

cnt = Counter({0: 2, -1: 1, 1: 1})

即:

cnt[-1] == 1 cnt[0] == 2 cnt[1] == 1 cnt[999] == 0 # 不存在的键返回 0(这是 Counter 的特性!)

✅ 关键优势:访问不存在的键不会报错,而是返回 0,这正是你代码中cnt[-x-y]安全的原因!


三、完整执行流程示例

输入:

nums1 = [1, 2] nums2 = [-2, -1] nums3 = [-1, 2] nums4 = [0, 2]

目标:找满足a + b + c + d == 0的元组数量。

Step 1: 构建cnt(a + b 的频次)

a+b: 1 + (-2) = -1 1 + (-1) = 0 2 + (-2) = 0 2 + (-1) = 1 cnt = {-1:1, 0:2, 1:1}

Step 2: 遍历c + d,查- (c + d)是否在cnt

c+d: -1 + 0 = -1 → 需要 a+b = 1 → cnt[1] = 1 -1 + 2 = 1 → 需要 a+b = -1 → cnt[-1] = 1 2 + 0 = 2 → 需要 a+b = -2 → cnt[-2] = 0 2 + 2 = 4 → 需要 a+b = -4 → cnt[-4] = 0 总和 = 1 + 1 + 0 + 0 = 2

✅ 返回2,正确。


四、为什么用Counter而不是普通dict

你可以用普通dict,但需要手动处理默认值:

# 手动写法(不推荐) d = {} for x in nums1: for y in nums2: d[x+y] = d.get(x+y, 0) + 1 total = 0 for x in nums3: for y in nums4: total += d.get(-(x+y), 0)

Counter自动处理缺失键为 0,代码更简洁安全:

# 你的写法(推荐) cnt = Counter(x+y for x in nums1 for y in nums2) return sum(cnt[-x-y] for x in nums3 for y in nums4)

✅ 这正是Counter在此场景下的最大价值!


五、复杂度分析

步骤时间空间
构建cnt(O(n^2))(O(n^2))(最坏所有和都不同)
遍历nums3+nums4(O(n^2))(O(1))
总计(O(n^2))(O(n^2))

远优于暴力 (O(n^4))。


总结

  • Counter基于哈希表的字典子类,用于计数。
  • 在你的代码中,它存储了nums1 + nums2所有可能和的出现次数
  • 利用Counter访问不存在键返回 0的特性,使得cnt[-x-y]安全且简洁。
  • 整体算法是空间换时间的典型应用,将四重循环降为两个双重循环。
http://www.jsqmd.com/news/89246/

相关文章:

  • 团队作业5 —— 测试与发布
  • 贾子战略理论体系(一套兵法、两个七十二、三大定律)| Kucius Strategic Theory (One Art of War, Two Seventy-Twos, Three Core Law
  • 家政公司怎么去网上接单?不烧钱、不瞎投,也能把单接满
  • 【节点】[Adjustment-ReplaceColor节点]原理解析与实际应用
  • 最近在研究高速列车的主动悬挂系统,发现H无穷控制策略在这个领域挺有意思的。今天就来聊聊基于H无穷控制策略的横摆半车9自由度高速列车主动悬挂
  • android开发compose系列之Icon
  • 重构智慧书-第13条:先知他人别有所图的心思,再伺机行事
  • LED照明技术趋势解读与选购关键参数指南
  • 两次大作业--总结
  • 金属熔凝数值模拟这玩意儿玩起来真是上头,特别是用Fluent搞激光加工的时候。今天咱们就唠点干货,从热源跳舞到代码蹦迪,保准让你少走三年弯路
  • 哈希函数特性总结
  • 七自由度车辆动力学模型验证:基于Dugoff轮胎模型与CarSim的探索
  • 25
  • 129_尚硅谷_变量作用域
  • 探索改进蜣螂优化算法(IDBO):提升性能的多维度创新
  • 系统流异世探险动态漫制作2025推荐,全方位解析
  • LaTeX | 文档单位排版宏包选型与使用
  • 【JAVA项目】基于JAVA的养老院管理系统
  • 想让你的标书不废标应该这样做
  • AI大模型应用开发学习-22【20251213】
  • Ubuntu硬盘空间不够?一文带你理清过程的根分区无损扩容实战指南
  • 最近在实验室折腾三相逆变器的控制方案,发现双闭环结构真是越玩越有意思。今天就拿Simulink仿真过程当案例,聊聊那些让人又爱又恨的调试细节
  • JMeter自搭与商用压测平台:效率成本对比及最优方案推荐
  • vscode c / cpp 关闭红色波浪线
  • 爬取京东商品评论 - f
  • 前端技术风险防控:以防为主,防控结合
  • 006发布文章测试用例
  • XXL-TOOL v2.4.0 发布 | 布隆过滤器、Excel流式读写、高性能BeanCopy
  • 使用哈希函数存储密码时为什么要加“盐”?
  • 给女神发“在吗”,她回了个表情包是几个意思?—— 硬核探讨TCP 三次握手