• 剑指:二进制中1的个数


    题目描述

    实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。

    注意:

    • 负数在计算机中用其绝对值的补码来表示。

    样例1

    输入:9
    输出:2
    解释:9的二进制表示是1001,一共有2个1。
    

    样例2

    输入:-2
    输出:31
    解释:-2在计算机里会被表示成11111111111111111111111111111110,
          一共有31个1。


    判断是否为1的方法:1&1=1,即输入n&1=?


    解法

    解法一

    利用整数 1,依次左移每次与 n 进行与运算,若结果不为0,说明这一位上数字为 1,++cnt。

    此解法 i 需要左移 32 次。

    不要用 n 去右移并与 1 进行与运算,因为 n 可能为负数,右移时会陷入死循环。

    public class Solution {
            
        public static int numBitCount(int n){
            int i = 1;
            int cnt = 0;
            while(i != 0){
                if((n&i)!=0)
                    cnt++;
                i <<= 1; //即i = i << 1;
            }
            return cnt;
        }
    
        public static void main(String[] args) {  
            System.out.println(numBitCount(-1)); //res:32
        }
    }

    解法二(推荐)

    运算 (n - 1) & n,直至 n 为 0。运算的次数即为 n 的二进制中 1 的个数

    因为 n-1 会将 n 的最右边一位 1 改为 0,如果右边还有 0,则所有 0 都会变成 1。(n-1是n的右边第一位1变0,后面0变1)

    结果与 n 进行与运算,会去除掉最右边的一个 1

    举个栗子:

    若 n = 1100,
    n - 1 = 1011
    n & (n - 1) = 1000
    
    即:把最右边的 1 变成了 0。
    

    把一个整数减去 1 之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的 1 变成 0。很多二进制的问题都可以用这种思路解决。

     
    public static int numBitCount(int n){
            int cnt = 0;
        while(n != 0){
            cnt++;
            n &= (n-1); //n = n & (n-1)
        }
        return cnt;
    }
    
    
    

    解法三

    利用 Java API。

    class Solution {
    
        /**
         * 求二进制中1的个数
         *
         * @param n 整数
         * @return 该整数的二进制中1的个数
         */
        public int NumberOf1(int n) {
            return Integer.bitCount(n);
        }
    }
  • 相关阅读:
    sed匹配多行并替换其中的内容
    sysbench 安装、使用和测试
    linux inode号已满的解决办法
    Linux双网卡绑定
    es安装
    kibana安装
    filebeat
    Codeforces 464E The Classic Problem (最短路 + 主席树 + hash)
    Codeforces 1137C Museums Tour (强连通分量, DP)
    HDU 4921 Map(状态压缩)
  • 原文地址:https://www.cnblogs.com/lisen10/p/11067882.html
Copyright © 2020-2023  润新知