268 . Missing Number
题意:
已知一个包含n个整数的数组,包含数列0, 1, 2, …, n(有n+1个数)里面的n个数,要求求出数组与数列相比缺少的那个数。
实现以下函数:
class Solution {
public:
int missingNumber(vector<int>& nums) {
}
};
题解:
首先,我们会想到最简单直接的方法,就是把数组中的数全都加起来,然后计算0一直加到n的和,用数列的和减去数组的和,即可得到缺少的那个数。
代码实现如下:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int sum = 0;
int n = nums.size();
vector<int>::iterator it;
for(it=nums.begin();it!=nums.end();it++)
{
sum += *it;
}
return (1+n)*n/2 - sum;
}//缺点:int sum可能会爆掉。
};
然而,当我们提交之后,会发现,当n过大时,和sum爆掉了。
不得已,去看discuss的最佳解。
最佳解用到了位的异或运算,十分巧妙。
首先,我们先来基本了解一下位的异或运算。
参与运算的两个值,如果两个相应位相同,则结果为0,否则为1。即:
0^0=0, 1^0=1, 0^1=1, 1^1=00^0=0,0^1=1 可以看出,0异或任何数=任何数
1^0=1,1^1=0 可以看出 1异或任何数=任何数取反
任何数异或自己=把自己置0数a两次异或同一个数b(a=a^b^b)仍然为原值a.
接着,我们便可以尝试用异或运算来解这一道题了。
首先,代码如下:
class Solution {
public:
int missingNumber(vector<int>& nums) { //利用xor异或运算 ,可避免int爆掉
int res = nums.size();
for(int i=0; i<nums.size(); i++){
res ^= i;
res ^= nums[i];
}
return res;
}
};
举个例子,比如,我们得到一个数组[0,1,2,4,5],则res==5,在每一次for循环中,我们让5分别和i、nums[i]做异或运算,在5次循环后,res会和数列[0,1,2,3,4]和数组[0,1,2,4,5]都异或一遍,因为一个数a两次异或同一个数b(a=a^b^b)仍然为原值a,所以,初始值5在多次异或运算后,得到的结果就是只与5异或一次的数字,也就是缺的哪一个数字。
这种方法运用了位运算,计算十分快。