news 2026/7/7 3:08:03

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
​从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]安全且简洁。
  • 整体算法是空间换时间的典型应用,将四重循环降为两个双重循环。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 12:06:54

如何在spring boot项目中利用腾讯云上传存储文件

注册与登录 1.访问 腾讯云官网,注册并登录账号。完成实名认证(这是必须的)。 2.开通COS服务 这里有指引,一步步照着点确定就行 在控制台首页搜索“对象存储”或“COS”,进入产品页面,点击“立即使用”或…

作者头像 李华
网站建设 2026/7/7 9:45:18

【C++ 经典算法】贪心算法求解股票最大利润(兼容 C++98/03)

在股票交易策略分析中,“单次买卖最大化利润” 是经典的算法问题,贪心算法凭借 O (n) 时间复杂度、O (1) 空间复杂度的优势,成为该问题的最优解。本文将从原理、实现、兼容优化三个维度,详解贪心算法求解股票最大利润的完整方案&a…

作者头像 李华
网站建设 2026/7/6 16:10:07

K8S-蓝绿发布与金丝雀发布

一、蓝绿发布在Kubernetes中,蓝绿发布(Blue-Green Deployment) 是一种部署策略,通过同时维护两个完全独立的生产环境(“蓝”和“绿”),在验证新版本(绿)后,一…

作者头像 李华
网站建设 2026/7/7 14:21:20

并发编程的锁有哪些?怎么分类?

文章目录一、按【实现方式】分类1. synchronized(JVM内置锁)2. lock(JUC显示锁)二、按【线程是否阻塞】分类1. 阻塞锁2. 自旋锁三、 按【是否公平】划分1. 公平锁2. 非公平锁四、按【锁的重入性】划分1. 可重入锁2. 不可重入锁五、 按【锁的作用范围】划…

作者头像 李华
网站建设 2026/7/7 11:30:22

航空机票预定系统|基于springboot 航空机票预定系统(源码+数据库+文档)

航空机票预定 目录 基于springboot vue航空机票预定系统 一、前言 二、系统功能演示 ​三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取: 基于springboot vue航空机票预定系统 一、前言 博主介绍&am…

作者头像 李华
网站建设 2026/7/7 4:30:58

【奶茶Beta专项】【LVGL9.4源码分析】07-API映射管理

【奶茶Beta专项】【LVGL9.4源码分析】07-API映射管理1 概述1.1 文档目的1.2 代码版本与范围2 设计意图与总体定位2.1 问题背景2.2 API 映射头的角色2.3 设计目标2.4 本文分析对象与侧重点3 使用方法3.1 在 C/C 代码中的使用3.2 在绑定/自动生成工具中的使用3.3 从 v8 升级到 v9…

作者头像 李华