题目要求
想法
想法一:
使用高斯求和公式求出0->n中所有数字之和,然后用所有数字之和减去序列中的数,最后得到的便是序列中缺少的那个数。最开始的想法是想用哈希表,但考虑到用哈希表的话,空间复杂度O(N),时间复杂度O(N),想去降低空间复杂度O(N),便想到了使用高斯求和的方法。
代码:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int length = nums.size(),sum;
if(length%2==0) sum=(1+length)*(length/2);
else sum=(1+length)*(length/2)+length/2+1;
for(int i=0;i<nums.size();i++)
sum-=nums[i];
return sum;
}
};
运行结果:
总结与反思:
高斯求和方法无论在时间和空间上都具有非常好的效率,但是如果输入的n非常大时,求和会很容易溢出int的表示范围。虽然在这个题上,高斯求和的方法通过了,但是还是不太建议使用高斯求和的方法。
想法二:
位运算,这是我从Leetcode题解和csdn博客上看到的方法,感觉牛人还是多啊,哈哈。因为异或运算满足交换律和结合律,对相同的数进行两次异或运算结果还是自己(example: x^y^y = x),利用这个性质我们可以对0->n和序列进行位运算,最后得到的结果就是缺失的值,因为缺失的值在0->n和序列中只出现了一次,其他的值都出现了两次,相当于缺失的值对其他所有的值进行了两次异或运算,所以得到的还是缺失的值。
代码:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int res = nums.size();
for(int i=0;i<nums.size();i++){
res ^= i;
res ^= nums[i];
}
return res;
}
};
运行结果:
总结与反思:
相比较两个想法的消耗时间是比较接近的,区别是一个要进行加法运算另一个不进行加法运算,这样就避免了因为求和而导致的数值溢出问题。其他思路比如排序,虽然比较容易想,但是时间复杂度最低O(nlogn),所以就不再考虑。
Leetcode 448 找到数组中所有消失的数 后更。
想法三
遍历数组,用数组中对应的值,去相应的index上加上数组的size()。比如[1,1,2],nums[0]=1,那么nums[1]加上3,nums[2]=2,那么nums[2]加上3,nums[1]=1,那么nums[1-1]加上3,最后得到[1,7,5]。而nums[0]<3,所以缺1,对于多余的数原理相同。虽然最后的实现有一点不同。
代码
class Solution {
public:
int missingNumber(vector<int>& nums) {
nums.push_back(nums[0]);
for(int i=0;i<nums.size();i++){
int index = nums[i]%nums.size();
nums[index] += nums.size();
}
int i;
for(i=0;i<nums.size();i++){
if(nums[i]<nums.size())
break;
}
return i;
}
};
运行结果
总结与反思
题做多了之后,多去总结,有很多方法是通用的,一定要做到一题多解。加油。