zoukankan      html  css  js  c++  java
  • 15 二进制中1的个数

    题目描述:

     输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。例:表示成二进制是1001,有两位是1,因此函数返回2。

    测试用例:

     1)正数(包括边界值:1、0x7FFFFFFF(除了首位为0,其他都为1,最大的正数)

     2)负数(包括边界值 0x80000000(只有首位是1,其他位为0,”最小的负数“)、0xFFFFFFFF(所有位全是1,指-1)

     3)0

    解题思路:

     1)常规解法:

    n与二进制1相与,可以判断n的最低位是不是为1。接着把1左移1位变成2,再和n相与,能知道n的次低位是不是为1。。。

    //int 32 bit
    class Solution {
    public:
         int  NumberOf1(int n) {
             int count = 0;
             unsigned int flag = 1; 
             while(flag){
                 if(n&flag)
                     count++;
                 flag = flag<<1;
             }
             return count;
         }
    };

    循环的次数等于正数二进制的位数(int 32bit) 

    2)欣赏的解法  

     规律:把一个整数减去1(就是把最右边的1变成0,如1100-1=1011),再和原整数做运算,会把该整数的最右边的1变成0(1100&1011=1000)。那么一个整数的二进制表示中有多少个1,就可以进行多少个这样的操作。

    class Solution {
    public:
         int  NumberOf1(int n) {
             int count = 0;
             while(n){ //n!=0时(正数/负数),二进制中一定含有1.
                 count++;
                 n = n&(n-1);  //每运行一次,二进制中减少一个1
             }
             return count;
         }
    };
    

    3)使用右移运算,错误代码:当n是负数时,会陷入无限循环

    class Solution {
    public:
         int  NumberOf1(int n) {
             int count = 0;
             while(n){ 
                 if(n&1)
                     count++;
                 n = n>>1;
                 //当n为负数时,右移,高位用1补位,最后终所有位都是1(0xFFFFFFFF)陷入死循环
             }
             return count;
         }
    };  

    修改,对负数另做运算:负数首位一定是1,count计数加1。将其变为0,右移补位为0,同正数一样。

    class Solution {
    public:
         int  NumberOf1(int n) {
             int count = 0;
             if(n < 0){ //n为负数,把首位的1变0,count加1。剩下的按正数处理
                 n = n & 0x7FFFFFFF;
                 ++count; //n不为0,一定含有1
             }
             while(n != 0){
                 count += n & 1;
                 n = n >> 1;
             }
             return count;
         }
    };
    

    4)使用内建函数

    class Solution {
    public:
         int  NumberOf1(int n) {
            return bitset<32>(n).count();
         }
    };//
    

    -- bitset存储二进制数位,bitset中的一个元素一般只占1 bit。  

    -- bitset中的每个元素都能单独被访问,例如对于一个叫做foo的bitset,表达式foo[3]访问了它的第4个元素,就像数组一样。

    -- 整数类型和布尔数组都能转化成bitset。

    -- bitset的大小在编译时就需要确定。如果你想要不确定长度的bitset,请使用 vector<bool>。  

    -- bitset的运算就像一个普通的整数一样,可以进行与(&)、或(|)、异或(^)、左移(<<)、右移(>>)等操作。

    https://www.cnblogs.com/RabbitHu/p/bitset.html 

    https://www.cnblogs.com/magisk/p/8809922.html  

    基础知识:

    [1] 位运算有5种操作:与&、或|、异或^、左移<<、右移>>。

    左移 m<<n :最左边的n位将被抛弃,同时在最右边补上n个0。

    右移 m>>n:

    -- 如果数字是无符号数值,用0填补左边的n位

    -- 如果数字是有符号数值,则用数字的符号位填补最左边的n位

               正数:右移,左侧补n个0

               负数:右移,左侧补n个1

    [2] 右移1位相当于除以2运算,因为除法的效率比移位运算要低的多,在实际的编程中应该尽可能的用移位代替除法

    [3] 因为右移对正负的补位不同,在编写程序时尽量使用左移。 

  • 相关阅读:
    [湖南集训]谈笑风生
    【SCOI2010】序列操作
    ●BZOJ 3994 [SDOI2015]约数个数和
    ●BZOJ 3309 DZY Loves Math
    ●UOJ 21 缩进优化
    ●BZOJ 2693 jzptab
    ●BZOJ 2154 Crash的数字表格
    ●BZOJ 3529 [Sdoi2014]数表
    ●2301 [HAOI2011] Problem b
    ●BZOJ 2820 YY的GCD
  • 原文地址:https://www.cnblogs.com/GuoXinxin/p/10400581.html
Copyright © 2011-2022 走看看