剑指offer——二进制中1的个数(好题,原码,反码,补码相关)

来源:互联网 发布:ubuntu debian 编辑:程序博客网 时间:2024/05/22 06:20

面10(相关题目很好)
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

背景补充:
int的有符号整数范围-2147483648~+2147483647
(注意,无符号整数和有符号整数,相同位数所能表示的数字个数是一样的)
(正数最高位是0,负数最高位是1)
-2147483648的补码是100…0(31个0)

原码表示法是机器数的一种简单的表示法。其符号位用0表示正号,用1表示负号,数值一般用二进制形式表示。

机器数的反码可由原码得到。如果机器数是正数,则该机器数的反码与原码一样;如果机器数是负数,则该机器数的反码是对它的原码(符号位除外)各位取反而得到的。

机器数的补码可由原码得到。如果机器数是正数,则该机器数的补码与原码一样;如果机器数是负数,则该机器数的补码是对它的原码(除符号位外)各位取反,并在末位加1而得到的。

  1. 计算机里面,只有加法器,没有减法器,所有的减法运算,都必须用加法进行。
  2. 用补数代替原数,可把减法转变为加法。出现的进位就是模,此时的进位,就应该忽略不计。
  3. 二进制下,有多少位数参加运算,模就是在 1 的后面加上多少个 0。
  4. 补码就是按照这个要求来定义的:正数不变,负数即用模减去绝对值。

思路:
想到要用位运算(相对于除2取余,运算速度更快),每次都和1位与,结果是1,说明最低位为1。
注意要使用无符号右移,因为负数的符号位是1,如果是有符号右移就会补1。

public int NumberOf1(int n) {        int count = 0;        while(n!=0){            if((n&1)!=0)                count++;            n = n>>>1;        }    return count;      }

或者,把对比的数字每次左移一位。

    public int NumberOf1(int n) {        int count = 0;        int flag = 1;        while (flag != 0) {            if ((n & flag) != 0) {                count++;            }            flag = flag << 1;        }        return count;}

把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

    public int NumberOf1(int n) {           int count = 0;           while(n!= 0){               count++;               n = n & (n - 1);           }           return count;       }

相关题目
这里写图片描述