剑指offer-test11

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循环

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值