统计二进制展开中数位1的个数的优化

问题:

  对于任意的非负整数,统计其二进制展开中数位1的总数。



解决:

  相关Blog:http://www.cnblogs.com/maples7/p/4324844.html

  在看这篇之前可以先看看上述这篇,这篇主要讨论其优化问题。

常规解法:

O(logn):

 1 int countOnes(unsigned int n)
 2 {
 3     int ones = 0;
 4     while (0 < n)
 5     {
 6         ones += (1 & n);
 7         n >>= 1;
 8     }
 9     return ones;
10 }

无非就是每次取其二进制展开最后一位,是1就计数。

效率由位运算可知(右移一位等价于除以2),为 O(logn)。

优化解法1:

O(countOnes(n)):

 1 int countOnes1(unsigned int n)
 2 {
 3     int ones = 0;
 4     while (0 < n)
 5     {
 6         ones++;            // 计数(最后至少有一位为1)
 7         n &= n - 1;        // 清楚当前最靠右的1
 8     }
 9     return ones;
10 }

解释如下:

优化解法2:

O(logW), W = O(logn) 为整数的位宽, 实际上就是 O(1) 的算法

代码及解释:

这个算法是一种合并计数器的策略。把输入数的32Bit当作32个计数器,代表每一位的1个数。然后合并相邻的2个“计数器”,使i成为16个计数器,每个计数器的值就是这2个Bit的1的个数;继续合并相邻的2个“计数器“,使i成为8个计数器,每个计数器的值就是4个Bit的1的个数。。依次类推,直到将i变成一个计数器,那么它的值就是32Bit的i中值为1的Bit的个数。

From : 《数据结构习题解析》,邓俊辉

Reference:

1、http://blog.chinaunix.net/uid-21275705-id-224360.html

2、http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive

时间: 2024-10-06 22:05:21

统计二进制展开中数位1的个数的优化的相关文章

统计一个字符串中的单词的个数,并打印各个单词

/*测试数据:Shen zhen is a beautiful city!*/ /*运行结果:Word:6 Shen zhen is a beautiful city!*/ #include<stdio.h> #define SIZE 1000 void wordCount(char *str) { int count = 0, flag = 0; char *p = str; while (*p != '\0'){ while (*p == 32){ if (*(p + 1) == 0){/

统计&quot;面&quot;要素中&quot;点&quot;要素的个数.

步骤 1,创建字段 IFields 1 /// <summary> 2 /// 创建:"面"-"点数"的字段. 3 /// </summary> 4 /// <returns></returns> 5 public static ESRI.ArcGIS.Geodatabase.IFields CreateFields() { 6 ESRI.ArcGIS.Geodatabase.IField fieldId = new

统计js数组中奇数元素的个数

如何统计一个JS数组中奇数元素的个数呢? 这是群友提出的一个问题,大部分群友给出的是遍历 然后对2取模,得到最终结果. 这样的写法是最容易想得到的,那么有没有其他思路呢? 这里我提供另外一种思路,我们知道奇数其实就是以 1 3 5 7 9 作为末尾结尾的数字,那么只要统计这些数字出现的次数就够了,但是光这样统计容易误算,所以我们可以先用逗号拼接起来,连着逗号一起计算,由于js没有php那么方便的能用substr_count 函数统计字符串出现次数,所以我们直接采用正则替换,计算长度差得到个数,代

统计一行字符中各类字符的个数

/*输出一行字符,分类统计字符个数*/ #include<stdio.h>#include<stdlib.h>int main(void){ int letter=0,space=0,digit=0,other=0;/*定义变量并初始化*/ char c;/*定义字符串c*/ printf("请输入一行字符,以回车键结束\n"); while((c=getchar())!='\n')/*判断c是否是回车键*/ if(c>='a'&&c<

0x00到0xFF二进制数值中1的的个数

似乎有点无聊耶~~~~~(>_<)~~~~ 1 #include <stdio.h> 2 3 static char gCharDotTab[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; 4 static char gDotNum[256] = { 5 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 6 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,

统计numpy数组中每个值的个数

import numpy as np from collections import Counter data = np.array([1.1,2,3,4,4,5]) Counter(data) #简单方法 sum(data==4) 原文地址:https://www.cnblogs.com/wzdLY/p/9630717.html

JS实现如何的统计一个字符串中相同的字符个数

  1 var string="start,stop,speed,start,speed,start,relocicty,start,start,start,start"; 2 var count=1; 3 for (let index = 0; index < string.length; index++) { 4 var a=string.indexOf("start",index); 5 // console.log(a); 6 if(a!=-1&

剑指Offer面试题10(Java版):二进制中的1的个数

题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数.例如把9表示成二进制是1001,有2位是1,因此如果输入9,该函数输出2. 1.可能引起死循环的解法 这是一道很基本的考察二进制和位运算的面试题.题目不是很难,面试官提出问题之后,我们很快形成一个基本的思路:先判断证书二进制表示中最右边一位是不是1.接着把输入的证书右移一位,此时原来处于从右边树起的第二位被移到最后一位,再判断是不是1.这样没移动一位,知道整个整数变成0为止.现在的问题变成怎么判断一个整数的最右边是不是1了.这很简

【c语言】统计一个数二进制中的1的个数

// 统计一个数二进制中的1的个数 #include <stdio.h> int count(int a) { int count = 0; while (a) { count++; a = a & (a - 1); } return count; } int main() { printf("%d\n", count(10)); printf("%d\n", count(0)); printf("%d\n", count(-