关于比特为1的计数算法

来源:互联网 发布:手机交友软件排名 编辑:程序博客网 时间:2024/05/15 17:34

问题描述:

        给定一个32(2^n)比特的整数,用一个算法计算出其中包含的1的个数。

问题分析:

      对于该问题,最容易想到的算法就是穷举算法,对该整数的每个比特进行扫描计数,对于一个包含n比特的整数,该算法的时间复杂度为O(n),空间复杂度为O(1)。

算法如下(C语言):

int  count(unsigned int i)

{

    int count = 0;

    for(int j=0;j<32;j++)

   {

       if((i>>j) & 1)

            count++;

   }

  return count;

}

 

算法解析:

        该算法在最好和最坏情况下的复杂度一样,都为O(n), n为比特数。

 

第二种方法:

     对于第二种方法,其最坏复杂度和第一种一样,但最好的情况下为O(1),平均复杂度仅为第一种的一半。

算法(C语言):

   int count(unsigned int i)

  {

     int count = 0;

     while(i)

    {

     count++;

    i = i & (i-1);

     }

  }

 该算法仅对比特为1的进行计数,每次循环计算一个比特为1的位,该算法的时间复杂度还是O(n),但是效率比之第一种算法平均要快上一倍。

第三种算法:

 这种算法的时间复杂度为O(logN),还是先给出算法的描述,然后再进行分析。

算法(C语言):

 int count(unsigned int i)

{

    i = (i & 0x55555555UL) +(( i>>1) & 0x55555555UL);

    i = (i & 0x33333333UL) + ((i>>2) & 0x33333333UL);

    i = (i & 0x0F0F0F0FUL) + ((i>>4) & 0x0F0F0F0FUL);

   i = (i & 0x00FF00FFUL) + ((i>>8) & 0x00FF00FFUL);

   i = (i & 0x0000FFFFUL) + (i >>16) & 0x0000FFFFUL);

  return i;  

}

算法分析:

 该算法首先将32比特的整数分成16组,每两个相邻的比特分为一组,分组计算每组的比特为1的数量,

对于一个整数如:xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxy,b分为两部分后,第一部分为i & 0x55555555UL,

第二部分为:(( i>>1) & 0x55555555UL),由于0X55555555UL的二进制为01010101010101010101010101010101b, 这样,用i与之进行与操作之后,相当于只是取了奇数部分的比特,结果为0y0y0y0y0y0y0y0y0y0y0y0y0y0y0y0yb,

而第二部分则先进行一个比特的移位之后,再进行一个与操作,结果为0x0x0x0x0x0x0x0x0x0x0x0x0x0x0x0xb,

(x和y为0或者1),然后把这两部分的结果相加,可以看出,0x + oy结果可能为00,01,10,  而这两比特中所保存的结果就是在原来的整数中xy部分的比特为1的个数。(如果1为1,y为0,则只有一个1比特,此时结果为01,同样,若x,y均为1,则结果为10,也是表示只有2个比特为1,其它为0或者1的情况同样成立),这样在结果i中保存16组(每组2比特)的1的个数,然后再将这个16组分成8组,每组四比特(即前面的2个2比特),将4比特中的前2比特进行移位与后两比特对齐,再进行相加,此时在结果4比特中的保存的就是这原来4比特中1的个数(因为前面的结果中每组2比特中最大为10,这样相加后,最大值为0100,表示的还是这4个比特中为1的个数,而且不会向前部分产生进位),然后再放大到8比特组,最后到16比特组,得到的结果就是该整数中比特为1的个数。

原创粉丝点击