LeetCode 剑指Offer 53 - II 0~n-1中缺失的数字
题目
解题
解题一:遍历 + 异或
思路:数组长度为 n,寻找第一个 nums[i] > i
的位置,返回 i
,若是所有位置都满足 nums[i] == i
,返回 n
。
// javascript
var missingNumber = function(nums) {
const n = nums.length;
for (let i = 0; i < n; ++i) {
if (nums[i] !== i) return i;
}
return n;
};
还有一种办法是使用异或,最后没有被抵消的数字就是要找的数字。利用的规律是 A xor A = 0
,0 xor A = A
,A xor B = B xor A
:
// javascript
var missingNumber = function(nums) {
const n = nums.length;
let res = 0
for (let i = 0; i < n; ++i) {
res ^= nums[i];
res ^= (i + 1);
}
return res;
};
比如 [0, 1, 3] 的 res 计算结果是 (((0 xor 0 xor 1) xor 1 xor 2) xor 3 xor 3)
,最后结果是 2
。
时间复杂度是 O ( n ) O(n) O(n),因为是排序数组,所以更优的方法是二分查找。
解题二:二分查找
转换成二分查找来做,返回值的范围是 [0, n]
,left
初始为 0
,right
初始为 n
。
// javascript
var missingNumber = function(nums) {
const n = nums.length;
let left = 0, right = n;
while (left < right) {
const mid = left + ((right - left) >> 1);
// 因为要寻找第一个 nums[i] > i,所以在左半边寻找
if (nums[mid] > mid) {
right = mid; // [left, mid]
} else {
// nums[mid] === mid
left = mid + 1; // [mid + 1, right]
}
}
return left;
};
解题三:数学-等差数列求和
如果数字齐全,所有数字可以组成一个等差数列,和为 s u m = n ∗ ( n + 1 ) 2 sum = {n * (n + 1) \over 2} sum=2n∗(n+1),用 s u m sum sum 减去数组中所有数字,最后得到的是缺失的数字。
// javascript
const n = nums.length;
let sum = (n * (n + 1)) / 2;
for (const x of nums) {
sum -= x;
}
return sum;
};