1、总结
- 从方法二看出来,LeetCode的算法场景,其实有很多特定的条件,例如:数据从 0 到 n、一定有一个元素缺失;
- Array.sort()
请注意,数组在原数组上进行排序,不生成副本
异或运算符的原理和运用知识,位运算符
- 高斯公式:
2、问题
Given an array containing n distinct numbers taken from 0, 1, 2, …, n, find the one that is missing from the array.
Example 1:
Input: [3,0,1]
Output: 2
Example 2:
Input: [9,6,4,2,3,5,7,0,1]
Output: 8
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
3、我的解法
方法一:先排序再找缺失元素
(虽然题目要求定存消耗,但我还是想从简单的写起)
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function(nums) {
let sortedNums = nums.sort((a, b) => {
return a - b;
});
console.log('sortedNums', sortedNums);
for(let i = 0; i < nums.length; i++) {
if(sortedNums[i] != i) {
return i;
}
}
return nums.length;
};
时间复杂度和空间复杂度都很差
,这里有一个陷阱:如果缺失的元素是最后一个元素,则需要帮它补齐。
方法二:计算总和,用减法得到缺失元素 受方法一中发现的陷阱引导,数组的最大值等于nums.length。已知数组的长度为nums.length,完整的数组长度应该是nums.length+1,数组元素应该是 [0, 1, 2, …, nums.length],则所有元素的总和为: ( 0 + nums.length) * (nums.length+1) / 2
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function(nums) {
let maxNum = nums.length;
let totalAmount = (0 + maxNum) * (maxNum+1) / 2;
for(let i = 0; i < maxNum; i++) {
totalAmount -= nums[i];
}
return totalAmount;
};
这个方法倒是满足了题目固定内存消耗的要求,时间和空间复杂度也快了很多,但是看比例还不是最优解。
4、其他解法
方法一:排序方法的优化
Array.sort() 方法会变更原来的数组,不产生副本,因此方法一不需要用额外的变量承接排序的结果,去掉这一步,性能会节省一点:
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function(nums) {
nums.sort((a, b) => {
return a - b;
});
// console.log('nums', nums);
for(let i = 0; i < nums.length; i++) {
if(nums[i] != i) {
return i;
}
}
return nums.length;
};
方法三:位运算 这个解法的原理其实我不是很懂,额外贴出算法原理供学习
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function(nums) {
let result = nums.length;
for(let i = 0; i < nums.length; i++) {
result ^= i ^ nums[i];
}
return result;
};
不得不承认位运算的速度是最快的,不过异或运算符的原理和运用知识还比较欠缺
发现solution 的解法跟我的方法二运用同一个原理:高斯公式,还是挺开心的。
方法四:创建完整的元素Map,遍历所有的nums元素,不在map中的则返回结果
方法四:遍历所有的nums.length+1元素,不在nums中的则返回结果
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function(nums) {
for(let j = 0; j < nums.length+1; j++) {
if(nums.indexOf(j) < 0) {
return j;
}
}
};
这个解法是时间复杂度最差的,应该是O(n2),空间复杂度O(1)