目录
题目:
略;
思路:
先将输入的两个数做异或运算,得到结果n,再统计n二进制序列中有几个1.
要点:
1、如何计算整数的二进制表示中有几个1?
方法一:解释见方法注释;注意这里对1进行左移运算,而不是对num进行右移运算,负数的二进制表示见补充一;while循环的条件是flag!=0,那么一共循环了多少次?见补充二。
/*
对于一个整数,和1做与运算,如果为0,则最低位为0;
随后将1左移(这里不将num右移,是因为num有可能是负数)
*/
private int getOnes(int num){
int count = 0;
int flag = 1;
while(flag!=0){
if((num&flag) != 0)
count++;
flag = flag<<1;
}
return count;
}
方法二:解释见方法注释
/*
优化解法
对于一个整数(比如10,用二进制表示为1010),将这个整数减1,变成9(用二进制表示就是1001)
这个过程就是将10最低位上的1以及其后所有的位取反,这些位置在将n和n-1(10和9)做与操作之后,都变成0
*/
private int getOnes2(int num){
int count = 0;
int flag = 1;
while(num!=0){
count++;
num = num&(num-1);
}
return count;
}
解法:
class Solution {
public int hammingDistance(int x, int y) {
int inputNum = x^y;
return getOnes2(inputNum);
}
/*
对于一个整数,和1做与运算,如果为0,则最低位为0;
随后将1左移(这里不将num右移,是因为num有可能是负数)
*/
private int getOnes(int num){
int count = 0;
int flag = 1;
while(flag!=0){
if((num&flag) != 0)
count++;
flag = flag<<1;
}
return count;
}
/*
优化解法
对于一个整数(比如10,用二进制表示为1010),将这个整数减1,变成9(用二进制表示就是1001)
这个过程就是将10最低位上的1以及其后所有的位取反,这些位置在将n和n-1(10和9)做与操作之后,都变成0
*/
private int getOnes2(int num){
int count = 0;
int flag = 1;
while(num!=0){
count++;
num = num&(num-1);
}
return count;
}
public int numberOf1(int n){
int count = 0;
int count1= 0;
int flag = 1;
while(flag!=0){
if((n&flag)!=0){//位运算符的优先级问题
count++;
}
flag = flag<<1;
count1++;//一共循环32次
}
return count;
}
}
ps:函数numberOf1是用来测试循环多少次的。
补充:
1、负数的二进制表示方法
以负数-5为例:
- 先将-5的绝对值转换成二进制,即为0000 0101;
- 然后求该二进制的反码,即为 1111 1010;
- 最后将反码加1,即为:1111 1011
ps:所以Java中Integer.toBinaryString(-5)结果为11111111111111111111111111111011. Integer是32位(bit)的.
2、将1左移多少次会变成0?
实验证明,左移32次或超过32次,会变成0.
3、位运算的优先级
ps:一元运算符>四则(包括%)>位移运算符>比较运算符(包括instanceof)>位逻辑运算符>逻辑运算符>三目运算符>赋值运算符;参考 位运算符优先级