ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

深入解析「第一个唯一偶数元素」:两趟遍历 + 哈希计数的标准解法(codeforces-go 实战)

深入解析「第一个唯一偶数元素」:两趟遍历 + 哈希计数的标准解法(codeforces-go 实战) 科学计算【免费下载链接】codeforces-go算法竞赛模板库 by 灵茶山艾府 项目地址https://gitcode.com/GitHub_Trending/co/codeforces-go点击查看免费下载本文以 LeetCode 第 178 场双周赛第一题 first-unique-even-element 的官方题解为骨架结合开源算法模板库 codeforces-go 中该题的 Go 实现、测试用例与测试驱动系统讲解两趟遍历 哈希计数这一基础而重要的计数范式。读完本文你将掌握该题在 Python/Java/C/Go 四种语言下的标准写法、复杂度推导以及 codeforces-go 仓库如何用RunLeetCodeFuncWithFile驱动题解完成自动化评测。一、题目背景与题意该题出自 LeetCode 第 178 场双周赛 A 题题目链接与函数签名可参见 a_test.go 中的注释。核心诉求可以概括为给定整数数组nums返回第一个既是偶数、又在数组中恰好出现一次的元素若不存在这样的元素返回-1。从仓库中的 a.txt 可以看到两个典型的评测样例[3,4,2,5,4,6] 2 [4,4] -1样例一4出现了两次索引 1、4不满足恰好出现一次2是偶数且只出现一次且是满足条件的第一个元素故答案为2。样例二4出现两次没有满足条件的元素返回-1。题目有两个并列的筛选条件数值为偶数x % 2 0与出现次数恰为 1。两个条件缺一不可这是整个解法的核心约束。二、核心思路两趟遍历 哈希计数官方题解见 README.md给出的思路非常朴素且高效第一趟遍历遍历nums用哈希表也可以改用数组/计数桶统计每个数的出现次数。一个可选的优化是只对偶数x计数因为奇数元素永远不可能是答案提前过滤可以节省哈希表的键空间。第二趟遍历再次按原始顺序遍历nums检查nums[i]是否满足nums[i] % 2 0且cnt[nums[i]] 1一旦命中立即返回nums[i]。兜底逻辑遍历结束仍未命中返回-1。为什么第一趟与第二趟缺一不可单趟遍历无法判定恰好出现一次——必须等完整统计完成后才知道某个数在全数组中的出现次数第二趟必须按原始顺序扫描才能保证返回的是第一个满足条件的元素而不是任意一个先统计后查询的次序保证了结果与元素在数组中的相对顺序严格一致。三、四语言标准实现以下四段实现完整继承自官方题解 README.md可直接作为各语言下的标准答案。Python3哈希表Counterclass Solution: def firstUniqueEven(self, nums: List[int]) - int: cnt Counter(nums) for x in nums: if x % 2 0 and cnt[x] 1: return x return -1JavaHashMapmergeclass Solution { public int firstUniqueEven(int[] nums) { MapInteger, Integer cnt new HashMap(); for (int x : nums) { if (x % 2 0) { cnt.merge(x, 1, Integer::sum); } } for (int x : nums) { if (x % 2 0 cnt.get(x) 1) { return x; } } return -1; } }Cunordered_mapclass Solution { public: int firstUniqueEven(vectorint nums) { unordered_mapint, int cnt; for (int x : nums) { if (x % 2 0) { cnt[x]; } } for (int x : nums) { if (x % 2 0 cnt[x] 1) { return x; } } return -1; } };Go原生mapfunc firstUniqueEven(nums []int) int { cnt : map[int]int{} for _, x : range nums { if x%2 0 { cnt[x] } } for _, x : range nums { if x%2 0 cnt[x] 1 { return x } } return -1 }四段实现的关键差异点语言计数容器计数写入方式说明Python3collections.Counter一行完成统计Counter(nums)对全部元素计数未做偶数过滤JavaHashMapInteger,Integermerge(x, 1, Integer::sum)仅统计偶数写法最紧凑Cunordered_mapint,intcnt[x]仅统计偶数注意[]会自动插入默认值 0Gomap[int]intcnt[x]仅统计偶数与仓库源码 a.go 完全一致小提示Java 的HashMap与 Go 的map都只对偶数做计数第一趟里的if x%2 0过滤而 Python 的Counter统计全部元素。前者节省空间后者代码更短两者在复杂度量级上一致。四、复杂度分析官方题解README.md给出的结论时间复杂度$\mathcal{O}(n)$其中 $n$ 是nums的长度。两趟遍历各消耗 $\mathcal{O}(n)$哈希表的插入与查询期望均为 $\mathcal{O}(1)$故整体为线性时间。空间复杂度$\mathcal{O}(n)$最坏情况下所有元素均为偶数且互不相同哈希表需要存储 $n$ 个键。若在 Python 中使用Counter(nums)则第一趟对全部 $n$ 个元素计数其余语言实现只对偶数计数实际键数量最多为偶数个数但仍属于 $\mathcal{O}(n)$ 量级。值得补充的一点如果题目将数值范围限定得很小例如 $|x| \le 10^5$可以把哈希表替换为计数数组/桶空间退化为 $\mathcal{O}(V)$$V$ 为值域大小常数更小、无哈希冲突这也是题解中用哈希表或者数组这一括注的用意所在。五、codeforces-go 仓库中的源码级佐证该题在仓库中的落位是 leetcode/biweekly/178/a/共三个文件题解 a.go、测试驱动 a_test.go、用例数据 a.txt。5.1 题解实现与题解文档完全对齐a.go 中的firstUniqueEven与 README 的 Go 版本逐字一致先建map[int]int仅统计偶数频次再按原序查找第一个频次为 1 的偶数无果返回-1。文件头部还保留了出题/讲解者的 B 站空间注释方便追溯讲解视频。5.2 自动化评测链路RunLeetCodeFuncWithFilea_test.go 展示了仓库的通用评测范式——把题解函数与用例文件交给测试工具func Test_a(t *testing.T) { if err : testutil.RunLeetCodeFuncWithFile(t, firstUniqueEven, a.txt, 0); err ! nil { t.Fatal(err) } }其中RunLeetCodeFuncWithFile定义于 leetcode/testutil/leetcode.go它的工作流程可以拆解为读取用例文件a.txt通过trimSpaceAndEmptyLine剔除空行与首尾空白用反射reflect.TypeOf(f)取得被测试函数的输入参数个数fNumIn与返回值个数fNumOut按每fNumIn fNumOut行一组切分用例即一行输入 一行期望输出为一组a.txt中[3,4,2,5,4,6]与2构成一组[4,4]与-1构成一组逐组调用RunLeetCodeFuncWithExamples执行题解并比对输出。这种源码函数 文本用例文件的测试架构同一套工具还支持类题、多输出、指定用例号、超时检测isTLE等能力详见 leetcode/testutil/leetcode_test.go让仓库中上千道题解都能以几乎零模板代码的方式获得回归测试保障——firstUniqueEven本身就是一个最小的可复现示例。5.3 如何在本仓库运行该题的测试在仓库根目录执行 Go 测试命令即可复现上述用例go test ./leetcode/biweekly/178/a/ -run Test_a -v若两个样例全部通过测试会逐条报告Case 1、Case 2的结果。你也可以向 a.txt 追加输入行 期望输出行的成对数据需保证总行数能被 2 整除来扩充自己的边界用例。六、边界情况与易错点总结基于解法本身与仓库用例以下几点值得在实现与自测时重点核对无解返回 -1[4,4]这类唯一元素却不唯一的输入最容易踩坑务必保留兜底return -1。第一个的语义第二趟必须按nums原序扫描不能改为遍历哈希表键哈希表无序会破坏第一个的约束。偶数判定放在两处计数阶段只统计偶数可以减小哈希表规模查询阶段再次校验偶数可保证与计数口径一致Python 的Counter版本因统计了全部元素查询阶段尤其不能省略x % 2 0。大数组性能$n$ 规模较大时两趟线性扫描 期望 $\mathcal{O}(1)$ 的哈希操作即为最优复杂度无需排序排序会引入 $\mathcal{O}(n \log n)$ 并破坏原序语义。七、从一题看一类计数 顺序扫描的通用范式firstUniqueEven是频次统计 顺序查询这一双趟范式的典型样本同类题目往往只是筛选条件不同把偶数换成奇数/正数/特定区间思路不变把恰好出现一次换成出现次数为 k只需把cnt[x] 1改为cnt[x] k需要任意一个而非第一个时第二趟甚至可以省略直接遍历哈希键即可。掌握了先统计、后按序复查的框架再配合本仓库 copypasta 中丰富的模板如计数桶、前缀和等基础数据结构可以快速迁移到大量存在性 频次类题目上。赞分享科学计算【免费下载链接】codeforces-go算法竞赛模板库 by 灵茶山艾府 项目地址https://gitcode.com/GitHub_Trending/co/codeforces-go点击查看免费下载相关推荐3条命令装好50多个Codex技能awesome-codex-skills完整指南3条命令装好50多个Codex技能awesome codex skills完整指南 awesome codex skills 是一个 Codex 技能精选合集AI 技能AI 插件工作流自动化人工智能leetcode 每日一题 · 594. Longest Harmonious Subsequence最长和谐子序列哈希计数两轮遍历解法全解析leetcode 每日一题 · 594. Longest Harmonious Subsequence最长和谐子序列哈希计数两轮遍历解法全解析 本篇技术指文档教程知识库哈希集合求数组公共元素LeetCode 2956「找到两个数组中的公共元素」多语言解法与 Go 实现剖析哈希集合求数组公共元素LeetCode 2956「找到两个数组中的公共元素」多语言解法与 Go 实现剖析 导读 本文以本仓库 leetcode/biweekl科学计算上一篇Bowtie2高级功能局部比对与全局比对的应用场景下一篇突破硬件调试壁垒SMU Debug Tool开源方案的底层控制革命创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表