这里就稍微整理一下C++中典型的位运算算法。
题目1:(二进制中的1的个数)请实现一个函数,输入一个整数,输出该二级制表中1的个数。
int onesInNum(int num){
int count=0;
while(num){
count++;
num=(num-1)# //去掉一个1
}
return count;
}
相关题目:输入两个整数m和n。计算需要改变m的二进制表示中的多少位才能得到n。
题目2:位运算实现加法
int Add(int num1, int num2){
int sum, carry;
do{
sum=num1^num2; //加法非进位
carry=(num1&num2)<<1; //加发进位
num1=sum; //继续循环
num2=carry;
}while(num2);
return num1;
}
题目3:利用位运算实现两个数字的交换
void swap(int& a, int& b){
a=a^b;
b=a^b; //a^b^b=a
a=a^b; //a^b^a=b
}
题目4:(数组中只出现一次的数组)一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1)。
解析:不同与统计字符串中只出现一次的字符,这个没法用hash表实现,因为空间复杂度只能为Q(1)。所以这里得另辟蹊径。数字不同于字符另一个特征是可进行计算。这个题目比较特殊的地方在于其他数字都只出现两次。异或的一个性质:任何一个数字异或它自己等于0!
这里一种思路是先将数组中所有的数异或,这样得到那两个不同数字的异或值,其值肯定不为0,找到一个非0位,然后根据该位将数组分成两组,进行异或,最后得到的分别为那两个只出现一次的数字。
void findNumsAppearOnce(int *a, int len, int *num1, int *num2){
if(a==NULL || len<=0)
return;
int xo=0;
for(int i=0;i<len;i++)
xo=xo^a[i];
unsigned flag=findFirstSetBit(xo);
*num1=*num2=0; //这是设置0安全,不会对结果产生影响
for(int i=0;i<len;i++){
if(a[i]&(1<<flag))
*num1^=a[i];
else
*num2^=a[i];
}
}
int findFirstSetBit(int num){
int count=0;
while((num&(1<<count))==0 && count<8*sizeof(int)){ //移动的位数不超过int类型的最大位数
count++;
}
return count;
}