【位运算】二进制的1个数

本题出自牛客网的剑指offer专题

题目描述

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

看到这道题,我就想起之前做汇编实验的时候经常会遇到这种类型的题目,也算是司空见惯了。

如果要使用Java语言单纯只是想解决问题的话,那无疑是非常简单的,在Java的Integer类中有许多方法可以来统计数字二进制表示中1的个数。

如:

public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        char ch[] = Integer.toBinaryString(n).toCharArray();
        for(int i=0;i

甚至可以这样:

public class Solution {
    public int NumberOf1(int n) {
        return Integer.bitCount(n);
    }
}

但是如果只是调用别人写好的方法,那未免也太无趣了点。所以,我们还是尽量自己来实现算法来解决问题。

首先对问题进行分析,我们不难发觉我们可以使用一个变量count来存储这个数值使用二进制表示法中1的个数,那么如何判断呢?我们可以这样来做:使用1与输入的整数进行与操作,如果结果为1,则表示该整数的二进制表示的最低位的数为1,此时count++,再将其进行逻辑右移,在java语言中,“>>>”符号就是表示逻辑右移。

在这里,为什么要强调是逻辑右移呢?那是因为,如果我们使用“>>”算术右移的话,对于负数来说,进行算术右移,则最高位会补1,这样的话,我们就无法判断原来的数字的二进制表示法中有多少个1了。

Java代码如下:

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

如果说要使用C++代码来实现算法呢?那如果还是跟上面的Java代码一样可就行不通了,因为在C++中可没有“>>>”逻辑右移的符号供你使用。虽然也可以通过unsigned int对输入数n进行强转,变成无符号数字。但在这里,我想使用别的方法。

那么应该怎么办呢?

其实想法也非常简单。还是巧用与操作,判断n是否为0,若不为0则将count++,并将输入数n-1与原来的n进行与操作最后赋值黑n,直到n为0则退出循环,这样便能正确地统计出输入数的二进制数中1的个数了。

C++实现版本:

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

或许还有人不懂,其实你可以这样想一下。倘若n-1,那么n这个数字二进制的最右边的1就会变成0,而在其右边的0全都会变成1,此时若(n-1)与原来的n进行与操作,那么n原来最右边的1便会消失,按照这个逻辑一次循环直到n的二进制中全部的1都消失不见,那么此时的count则为输入数n二进制表示法中1的个数

你可能感兴趣的:(解题报告)