面试题 17.04. 消失的数字
题目描述
数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
注意:本题相对书上原题稍作改动
示例 1:
输入:[3,0,1] 输出:2
示例 2:
输入:[9,6,4,2,3,5,7,0,1] 输出:8
解法
方法一:排序
思考
\(0\ldots n\) 缺一个数。开布尔数组标记再扫空洞,正确但多用 \(O(n)\) 空间。
排序后下标应等于值,第一处失配即缺失;若都吻合则缺 \(n\)。
先 sort 再枚举,实现最短。时间 \(O(n\log n)\),适合先给出可工作的解。
我们可以先对数组 \(nums\) 进行排序,然后遍历排序后的数组,判断当前元素是否等于其下标,若不等,则返回下标即可。
否则遍历结束后,返回数组长度即可。
时间复杂度 \(O(n \times \log n)\),空间复杂度 \(O(\log n)\)。其中 \(n\) 为数组 \(nums\) 的长度。
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 | |
方法二:求和
思考
排序的对数因子可以去掉:完整区间和为 \(n(n+1)/2\),减去数组和即所缺。
一次求和、常数空间,避免比较与交换。
我们可以先求出 \(0\) 到 \(n\) 的和,然后遍历数组 \(nums\),将数组中的元素依次减去,最后剩下的值即为缺失的数字。
时间复杂度 \(O(n)\),空间复杂度 \(O(1)\)。其中 \(n\) 为数组 \(nums\) 的长度。
1 2 3 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 | |
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 | |
1 2 3 4 5 6 | |
方法三:位运算
思考
求和在语言整数较窄时可能溢出。
把 \(0\ldots n\) 与数组全部异或,成对抵消后剩下缺失值,无进位、亦无额外表。
我们可以使用异或运算,将 \(0\) 到 \(n\) 的所有数与数组 \(nums\) 中的数进行异或运算,最后剩下的值即为缺失的数字。
时间复杂度 \(O(n)\),空间复杂度 \(O(1)\)。其中 \(n\) 为数组 \(nums\) 的长度。
1 2 3 4 5 6 | |
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 11 | |