版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/82388007
位运算
C++里面的与、或、异或、按位取反分别是&
、|
、^
、~
符号。左移运算是<<
,左移后右边补n个0。右移运算是>>
,正数右移在左边补n个0,负数右移在左边补n个1。
二进制中1的个数
输出一个整数的二进制形式中1的个数。
可能引起死循环的解法
#include<bits/stdc++.h>
using namespace std;
//可能引起死循环的解法
int NumberOf1_Solution0(int n) {
int count=0;//计数
//只要n还不是0
while(n){
if(n & 1)//如果n和1相与为1,即最低位为1
count++;//记录一下
n=n>>1;//右移一位把最低位挤掉
//当是负数时,显然最左边会补1,这时候就停不下来了
}
return count;
}
int main(){
cout<<NumberOf1_Solution0(9)<<endl;
return 0;
}
常规解法
#include<bits/stdc++.h>
using namespace std;
//常规解法
int NumberOf1_Solution1(int n) {
int count = 0;//计1的个数
unsigned int flag = 1;//要测试某一位是否为1的测试值,初始测试最低位,所以用1
//当左移没有超过二进制位数
while (flag) {
//用测试值和数字相与,可以测试相应的位
if (n & flag)//相与为1,则那一位为1
count++;//记录之
flag = flag << 1;//测试值左移
}
//循环的次数等于整数二进制的位数,左移超过了最高位就自然变0退出循环了
return count;
}
int main(){
cout<<NumberOf1_Solution1(9)<<endl;
return 0;
}
能给面试官带来惊喜的解法
一个整数减去1,可以将其最右边第一个1一直到最右边为止的所有数位取反。如:
利用这个性质,原数和减去1之后的数做与运算,则可以去掉原数最右边的一个1,有多少个1就可以做多少次这样的运算。
#include<bits/stdc++.h>
using namespace std;
//能给面试官带来惊喜的解法
int NumberOf1_Solution2(int n) {
int count = 0;//计数
//循环直到数字中所有1全没了,就变成0结束
while (n) {
++count;//记录这个1
n = (n - 1) & n;//去掉这个最右边的1
}
return count;
}
int main() {
cout<<NumberOf1_Solution2(9)<<endl;
return 0;
}
相关题目
用一条语句判断一个整数是不是2的整数次方
二的整数次方中有且只有一个1,经一次上面的运算后势必变成0。
#include<bits/stdc++.h>
using namespace std;
bool is2Power(int n){
return !(n&(n-1));//注意'!'的优先级最高,要把里面东西括起来
}
int main(){
cout<<boolalpha<<is2Power(8)<<endl;
cout<<boolalpha<<is2Power(9)<<endl;
return 0;
}
计算m需要改变多少位才能变成n
先异或,就将不同的位标记成了1,再计算异或结果中1的个数。
#include<bits/stdc++.h>
using namespace std;
int howManyTransfer(int m,int n){
int k=m^n;//异或结果中将不同为标记成了1
//计算异或结果中1的个数
int count=0;
while(k){
k=k&(k-1);
count++;
}
return count;
}
int main(){
cout<<howManyTransfer(8,9)<<endl;
cout<<howManyTransfer(13,10)<<endl;
cout<<howManyTransfer(11,-1)<<endl;
return 0;
}