剑指offer之个人刷题历程记录

时隔两个月又继续刷题,有危机感的刷题。

二进制中1的个数

题目描述:
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
知识点:
位计算
解题思路:
拿到这个题,注意到题上说负数用补码表示,这个时候需要补一下补码的知识。首先要把一个整数转换成二进制,能想到的最笨的做法就是一直除以2。
循环取余,当除数最后商1的时候,完成运算。
!!!到求负数的补码完全没有思路!还是参考大神的算法!
注意点:
需要注意到整数分为,正整数和负整数。正整数的原码=补码=反码(符号位为0),负整数的原码和正整数的原码相同(符号位为1),反码为符号位保持不变,其他位取反。补码为反码+1。把这个生成的二进制数看成字符串?
大神算法思路:
感觉大神的思路永远摸不透!!!
链接https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8
1.如果一个整数不为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 count = 0;
        while(n!= 0){
            count++;
            n = n & (n - 1);
         }
        return count;
    }
}

2.看到讨论区其他人的算法,算是最容易理解的一个。

https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8
来源:牛客网
把这个数逐次 右移 然后和1 与,就得到最低位的情况,其他位都为0,
如果最低位是0和1与 之后依旧 是0,如果是1,与之后还是1。
对于32位的整数 这样移动32次 就记录了这个数二进制中1的个数了
补充右移的知识:
https://www.cnblogs.com/blog-cq/p/5793529.html
右移运算符<<使指定值的所有位都右移规定的次数。

1)它的通用格式如下所示:

value >> num

num 指定要移位值value 移动的位数。

右移的规则只记住一点:符号位不变,左边补上符号位

2)运算规则:

按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1

当右移的运算数是byte 和short类型时,将自动把这些类型扩大为 int 型。

例如,如果要移走的值为负数,每一次右移都在左边补1,如果要移走的值为正数,每一次右移都在左边补0,这叫做符号位扩展(保留符号位)(sign extension ),在进行右移

操作时用来保持负数的符号。

3)数学意义

右移一位相当于除2,右移n位相当于除以2的n次方
具体代码:

public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        int bool;
        for(int i=0;i<32;i++){
            bool=n>>i&1;
            if(bool==1){  
                count++;
            }

        }
        return count;
    }
}

总结:
理解错误函数,函数默认已经转换为二进制数。思考太狭窄,没有考虑到java的更多算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值