LeetCode 645. Set Mismatch
题目描述
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制成了集合里面的另外一个数字的值,导致集合丢失了一个数字并且有一个数字重复。
给定一个数组 nums 代表了该集合发生错误后的结果。找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例:输入 nums = [1,2,2,4],输出 [2,3]。其中 2 是重复的数字,3 是丢失的数字。
解题思路
本题本质上是在 1 到 n 这 n 个数字中,有一个数字出现了两次,有一个数字没有出现。我们需要找出这两个数字。
方法:计数数组
因为数组中的数字都在 [1, n] 范围内,我们可以使用一个长度为 n 的辅助数组(或直接在原数组上标记)来统计每个数字出现的次数。
- 创建一个长度为
n的数组res,初始值全为 0。 - 遍历
nums,对于每个数字num,将res[num - 1]的值加 1。 - 再次遍历
res(或遍历 1 到 n):- 如果
res[i] == 0,说明数字i + 1没有出现过,即丢失的数字。 - 如果
res[i] == 2,说明数字i + 1出现了两次,即重复的数字。
- 如果
- 返回
[重复数字, 丢失数字]。
为什么这是正确的?
每个数字理论上应该恰好出现一次。由于只有”一个重复、一个丢失”,统计完频次后,出现 0 次的必然是丢失的数字,出现 2 次的必然是重复的数字。其余数字出现次数均为 1。
这个方法的巧妙之处在于利用了数字范围和数组下标的对应关系,将数字本身映射到索引上作为计数槽位。
复杂度分析
- 时间复杂度:
O(n),其中n是数组长度。需要两次遍历,每次遍历都是 O(n)。 - 空间复杂度:
O(n),使用了一个大小为n的计数数组。
进阶:如果想达到 O(1) 额外空间,可以通过在原数组上用”取负数标记”或”异或运算”来实现,但上述计数法最为直观易懂。
代码
1 | package code.J645; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 𝒞𝒶𝓃𝒶𝓇𝓎!