剑指offer二进制中的1的个数

今日第二道题,你今天做了几道了?
在上题之前,小李子实名点赞一下牛客中剑指的题解改版,增加了牛客剑指的官方解答,看了感觉思路非常清楚,而且方法比较全,易错的点也会讲到,会不错滴~~~大大的表扬!!!

一定要坚持看完哦,最后有惊喜哦!!!

上题:

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

分析:这道题我之前看过,但是当时不会,没做对。虽然这次也不会,但是看了题解很清楚了~~
要求解1的个数,那我们要得到一个数的二进制,可以用/2取余法得到。

试试法:除二取余法(对非负数可行)
代码:
public class Solution {
    public int NumberOf1(int n) {
        int num=0;
        while(n!=0){
            int temp=n%2;
            n=n/2;
            if(temp==1){
                num++;
            }
        }
        return num;
    }
}
当然牛客是运行不通过的,因为没有考虑负数的情况,我们考虑的都是非负情况。
所以这种方法对所有整数行不通。

方法一:转二进制字符串再比较
利用Integer.toBinaryString()函数将数转为二进制字符串,在依次与1比较
代码:
public class Solution {
    public int NumberOf1(int n) {
        int num=0;
        String str=Integer.toBinaryString(n);
        char[] char1=str.toCharArray();
        for(char i:char1){
            if(i=='1')num++;
        }
        return num;
    }
}
牛客运行通过
运行时间:13ms
运行内存:9172Kb
这个方法真的还不错,哈哈哈~~
我们看点高级点的。


方法二:二进制移位法
Java中二进制移位的符号有左移>>  右移<<
我们可以设置一个二进制的1,通过移动这个1在32位中的位数,来和输入的数进行&操作。
注意一点java中的逻辑与和按位与
    逻辑与:&&,是两个boolean操作
    按位与:&   得到的是相同的个数,不只是1或者0;

代码:
public class Solution {
    public int NumberOf1(int n) {
        int num=0;
        int flag=0x01;
        while(flag!=0){
            if((flag&n)!=0)num++;
            flag<<=1;
        }
        return num;
    }
}
牛客运行通过
运行时间:14ms
运行内存:9412Kb
这种方法其实比较好理解,但是一些细微的东西容易出错。

方法三:神奇法?!
大神还给了另外一种方法,这是我在题解中看到的解释:
/**************************************************************************************/

如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

/**************************************************************************************/

代码:
public class Solution {
    public int NumberOf1(int n) {
        int num=0;
        while(n!=0){
            num++;
            n=n&(n-1);
        }
        return num;
    }
}
牛客运行通过
运行时间:17ms
运行内存:9288Kb
方法三相对于方法二,时间复杂度最坏为O(32),所以比方法二好一些,但是太难想了~~

举一反三:
(1)判断一个整数是否第2的整数次方;
举个栗子:2^1=2      10
         2^2=4     100
         2^3=8    1000
我们发现是否是整数次方,则该整数的二进制形式只有一个1,有转化为求解1的个数是否为1.
(2)两个整数m和n,判断m要改变几位才能变成n,其实还是二进制的问题。
    1、先将两个数进行异或处理。相同为0,不同为1;
    2、在求解1的个数,又转化为求1的个数。

今天写了很多,希望各位能学习到。
欢迎各位互相学习和交流哦~

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值