
本文介绍一种高效、简洁的方法,使用 collections.counter 统计频次并按原始列表中首次重复发生的位置顺序提取所有重复元素(即出现次数 ≥ 2 的元素),确保结果既准确又保持逻辑顺序。
在实际开发中,我们常需从一个列表中找出所有“重复出现”的元素,并按它们第一次成为重复项时的自然顺序组织结果——例如输入 [1,2,2,3,3,3,4,4,4,4],期望输出 [2,3,4](因为 2 在索引 2 首次重复,3 在索引 4,4 在索引 7);而输入 [1,2,24,2,1] 应返回 [1,2](1 在索引 4 首次重复,2 在索引 3,但因 1 更早出现在原列表前端,其重复实际先于 2 被“发现”?等等——注意:这里的关键是保留重复元素在原列表中首次出现的顺序,而非重复发生的顺序。题目示例 [1,2,24,2,1] → [1,2] 明确表明:结果应按该元素第一次出现的位置升序排列,且仅包含至少出现两次的元素。
原始递归代码存在两个核心问题:
- 逻辑错误:它仅检查首元素是否在后续子列表中存在,但未避免重复添加(如 [2,2,2] 中,第一个 2 和第二个 2 都会触发添加,导致 [2,2]);
- 顺序不可控:递归遍历虽保持访问顺序,但缺乏去重机制,无法保证每个重复元素仅被收录一次。
推荐解法是结合 collections.Counter 与列表推导式,兼顾效率与可读性:
from collections import Counter
def find_duplicates(list_of_numbers):
# 统计每个元素出现次数
counts = Counter(list_of_numbers)
# 按原列表顺序遍历,对每个元素检查是否重复,且仅首次遇到时添加(去重)
seen = set()
result = []
for num in list_of_numbers:
if counts[num] > 1 and num not in seen:
result.append(num)
seen.add(num)
return result✅ 此版本严格满足题设要求:
立即学习“Python免费学习笔记(深入)”;
- 输入 [1,2,2,3,3,3,4,4,4,4] → 输出 [1,2,3,4]?不,等等——再审题:示例输出是 [2,3,4],说明 1 未重复(只出现一次),正确;
- 输入 [1,2,24,2,1] → 1 出现 2 次,2 出现 2 次,24 出现 1 次 → 符合条件的为 1 和 2;按它们在原列表中首次出现的顺序:1(索引 0)、2(索引 1)、24(索引 2)→ 所以结果应为 [1,2],完全匹配。
⚠️ 注意事项:
- Counter 本身不保证键的插入顺序(Python 仅在其第一次出现时被加入结果,从而天然维持原始顺序;
- 时间复杂度为 O(n),空间复杂度为 O(n),远优于嵌套循环或低效递归;
- 若需兼容极旧 Python 版本(redDict 替代 Counter,但通常无需。
总结:避免手动递归模拟去重逻辑,善用标准库工具(Counter + 有序遍历 + set 辅助去重)是解决此类问题的最佳实践——简洁、健壮、符合 Pythonic 风格。










