11.二进制1的个数
这题涉及到符号“>>>”与符号“>>”的区别:
”>>”表示右移,也叫算法右移,最高位补符号位。如果该数为正,则高位补0,若为负数,则高位补1;
“>>>”表示无符号右移,也叫逻辑右移。即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。
方法1:将n减一后再和自身与“&”-----这样会将n最右边的1变成0
把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
(效率高,不容易理解)最优解的解决方式
public class Solution {
public int NumberOf1(int n) {
int count=0;
while(n!=0){
count++;
n=n&(n-1);
}
return count;
}
}
方法2:n右移(使用算数右移)
负数右移动,左边补1。所以将负数转成正数,这样再计算1的个数即可。
public class Solution {
public int NumberOf1(int n) {
int count=0;
for(int i=0;i<32;i++){
if(((n>>i)&1)==1){
++count;
}
}
return count;
}
}
方法3:使用无符号位移(可不用考虑整形的正负)
public class Solution {
public int NumberOf1(int n) {
int count=0;
while(n!=0){
if((n&1)==1){
count++;
}
n=n>>>1;//无符号右移
}
return count;
}
}
如果是下面这种可能会陷入死循环:
死循环具体是指:由于负数右移过程中高位填充1(高位填充符号位,负数符号位为1),最后会出现全1的情况,导致while(n)一直为真变成死循环
public class Solution {
public int NumberOf1(int n) {
int count=0;
while(n!=0){
if((n&1)==1){
count++;
}
n=n>>1;//符号右移
}
return count;
}
}
方法4:左移
flag用来比较每一位, 用与来比较每个位如果number的那一个位是1,则与flag的&操作结果一定不为0,如果那个位是0与flag的&操作结果为0,然后flag向左移一位,知道超过int的位数,flag最终变为0,结束整个循环。
(容易理解,但效率不高,因为根据flag判断循环结束条件,因此,每判断一个数都要循环32次。)
public class Solution {
public int NumberOf1(int n) {
int count=0;
int flag=1;
while(flag != 0){
if((n&flag) != 0){
count++;
}
flag=flag<<1;
}
return count;
}
}
方法5:转换为字符数组
public class Solution {
public int NumberOf1(int n) {
int count=0;
char[] charr=Integer.toBinaryString(n).toCharArray();
//toBinaryString返回值表示的无符号整数的二进制的字符串表示形式
//toCharArray()将字符串转换为字符数组
for(char ch:charr){
if(ch=='1'){
count++;
}
}
return count;
}
}
另外一种形式:
public class Solution {
public int NumberOf1(int n) {
int count=0;
String binStr=Integer.toBinaryString(n);
for(int i=0;i<binStr.length();i++){
if(binStr.charAt(i)=='1'){
count++;
}
}
return count;
}
}
二刷:
1.计算1的个数最简单的思绪就是
一个数和减去1后的数相与
n=n&(n-1);
直到这个数为0为止。
2.定义一个标记flag=1;
让flag和n相与
如果相与不为0,那么count++;
完成后,flag左移,循环至flag为0为止。
这样就知道有多少位1。
3.可以把这个整数变成字符串的形式。
使用的函数是
Integer.toBinaryString(n)将整数n转换为二进制无符号形式的字符串形式
a.进一步转换为字符数组使用函数toCharArray(),使用增强for循环
b.也可以直接用函数charAt()转换为字符,使用for循环