题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路:记住位运算的基本操作,与或非,异或,异或是两个数相同则为0,不同为1,理解为加法运算。一定记住。
还有就是将计算机表示位数定为32位或者64位,这样就可以遍历数的每一位,看是否为1.
这一题属于位运算的题目,两个数如果相同那么异或运算就为0,将一个变量初始化为0,再与其他数进行异或,不会改变结果,记住一定要记住异或是加法运算。
第一遍全部异或后,得到一个数flag,因为flag一定是两个不同的数异或得到的,那么flag等于1的那一位一定可以将这两个数分开,那么我们再用一次异或就分别找到了这两个数。
这题需要注意的是&的优先级比!=低,自己写的时候flag & bitflag != 0,导致想运算后面的!=,程序总是报错,一定要将判断条件加上括号,已经错了几次了。
记住:位运算就一个非常重要的公式,flag &(flag - 1),会将flag最后一位1去掉,一次flag - flag & (flag - 1)就是最后一个1,比如flag= 3,位表示位0110, flag & (flag - 1)=0100,减去之后0010.
class Solution { public: void FindNumsAppearOnce(vector<int> data,int *num1,int *num2) { int flag = 0; for(int i = 0;i < data.size();++i){ flag ^= data[i]; } int bitflag = 1; bitflag = flag - (flag & (flag - 1)); int left = 0,right = 0; for(int i = 0;i < data.size();++i){ if((data[i] & bitflag) != 0){ left ^= data[i]; } else{ right ^= data[i]; } } *num1 = left; *num2 = right; } };
下面的循环就low了,不好,不需要看了。
class Solution { public: void FindNumsAppearOnce(vector<int> data,int *num1,int *num2) { int flag = 0; for(int i = 0;i < data.size();++i){ flag ^= data[i]; } int bitflag = 1; int time = 32; while(time--){ if((flag & bitflag) != 0){ break; } bitflag = bitflag << 1; } int left = 0,right = 0; for(int i = 0;i < data.size();++i){ if((data[i] & bitflag) != 0){ left ^= data[i]; } else{ right ^= data[i]; } } *num1 = left; *num2 = right; } };