3289. 数字小镇中的捣蛋鬼
题目描述
数字小镇 Digitville 中,存在一个数字列表 nums,其中包含从 0 到 n - 1 的整数。每个数字本应 只出现一次,然而,有 两个 顽皮的数字额外多出现了一次,使得列表变得比正常情况下更长。
为了恢复 Digitville 的和平,作为小镇中的名侦探,请你找出这两个顽皮的数字。
返回一个长度为 2 的数组,包含这两个数字(顺序任意)。
示例 1:
输入: nums = [0,1,1,0]
输出: [0,1]
解释:
数字 0 和 1 分别在数组中出现了两次。
示例 2:
输入: nums = [0,3,2,1,3,2]
输出: [2,3]
解释:
数字 2 和 3 分别在数组中出现了两次。
示例 3:
输入: nums = [7,1,5,4,3,4,6,0,9,5,8,2]
输出: [4,5]
解释:
数字 4 和 5 分别在数组中出现了两次。
提示:
2 <= n <= 100nums.length == n + 20 <= nums[i] < n- 输入保证
nums中 恰好 包含两个重复的元素。
解法
方法一:计数
我们可以用一个数组 \(\textit{cnt}\) 记录每个数字出现的次数。
遍历数组 \(\textit{nums}\),当某个数字出现次数为 \(2\) 时,将其加入答案数组中。
遍历结束后,返回答案数组即可。
时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)。其中 \(n\) 为数组 \(\textit{nums}\) 的长度。
1 2 3 4 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
方法二:位运算
设数组 \(\textit{nums}\) 的长度为 \(n + 2\),其中包含 \(0 \sim n - 1\) 的整数,且有两个数字出现了两次。
我们可以通过异或运算来找出这两个数字。首先,我们对数组 \(\textit{nums}\) 中的所有数字以及 \(0 \sim n - 1\) 的整数进行异或运算,得到的结果为这两个重复数字的异或值,记为 \(xx\)。
接下来,我们可以通过 \(xx\) 找到这两个数字的某些特征,进而将它们分开。具体步骤如下:
- 找到 \(xx\) 的二进制表示中最低位或最高位的 \(1\) 的位置,记为 \(k\)。这个位置表示这两个数字在该位上是不同的。
- 根据第 \(k\) 位的值,将数组 \(\textit{nums}\) 中的数字以及 \(0 \sim n - 1\) 的整数分成两组:一组在第 \(k\) 位上为 \(0\),另一组在第 \(k\) 位上为 \(1\)。然后分别对这两组数字进行异或运算,得到的结果即为这两个重复数字。
时间复杂度 \(O(n)\),其中 \(n\) 为数组 \(\textit{nums}\) 的长度。空间复杂度 \(O(1)\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |