统计bytearray中的bitcount
给定一个byte数组,要求统计byte数组的bitcount,也就是byte数组中为1的位的个数。
Redis提供了位数组数据结构,位数组是相对独立的一个程序,在《Redis设计与实现》(黄建宏著)一书中,对此有详细介绍。
回到问题上来,看到这个问题的第一印象就是暴力。假设byte数组长度为n,那么时间复杂度为8n。
我们的目的就是优化常数。
很容易想到的是用空间换时间,预先打表0~255之间的全部数字的bitcount,用到时直接查表,复杂度将为O(n).
这种方法的缺点在于只能存储8位而不能存储太多,因为随着位数的增加,空间消耗指数级增长。
最高级的一种优化方法建立在位运算基础上。这种方法的思想基于分治算法。
首先两两一组分成16组,然后四四一组分成8组,八八一组分成4组,16、16一组分成两组。
统计各个组内1的个数,然后归并可以通过移位运算和加法运算实现。
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
int bitcountBruteForce(char*a,int len){
int s=0;
for(int i=0;i<len;i++){
for(int j=0;j<8;j++){
if(a[i]&(1<<j)){
s++;
}
}
}
return s;
}
int table[1<<8];
int bitcountTable(char*a,int len){
int s=0;
for(int i=0;i<len;i++){
s+=table[int(a[i]&0xff)];
}
return s;
}
int swar(int x){
x=(x&0x55555555)+((x>>1)&0x55555555);
x=(x&0x33333333)+((x>>2)&0x33333333);
x=(x&0x0f0f0f0f)+((x>>4)&0x0f0f0f0f);
x=(x*0x01010101)>>24;
return x;
}
int swar2(int x){
x=(x&0x55555555)+((x>>1)&0x55555555);
x=(x&0x33333333)+((x>>2)&0x33333333);
x=(x&0x0f0f0f0f)+((x>>4)&0x0f0f0f0f);
x=(x&0x00ff00ff)+((x>>8)&0x00ff00ff);
x=(x&0x0000ffff)+((x>>16)&0x0000ffff);//x=(x>>16)+(x&31);
return x;
}
int bitcountSWAR(char*a,int len){
int s=0;
int intLen=len/4;
int left=len%4;
int*ia=(int*)a;
for(int i=0;i<intLen;i++){
s+=swar2(*ia);
ia++;
}
for(int i=intLen*4;i<len;i++){
s+=table[a[i]];
}
return s;
}
void initTable(){
for(int i=0;i<(1<<8);i++){
int s=0;
for(int j=0;j<8;j++){
if(i&(1<<j)){
s++;
}
}
table[i]=s;
}
}
int timeit(int(*f)(char*,int),char*a,int len,int manytimes){
int begtime=time(0);
int res=0;
for(int i=0;i<manytimes;i++){
res=f(a,len);
}
cout<<"ans "<<res<<endl;
int endtime=time(0);
int timeused=endtime-begtime;
return timeused;
}
int main(){
const int n=1e6;
int a[n];
initTable();
srand(time(0));
for(int i=0;i<n;i++){
a[i]=rand();
}
cout<<"brute force "<<timeit(bitcountBruteForce,(char*)a,n*sizeof(int),10)<<endl;
cout<<"table method "<<timeit(bitcountTable,(char*)a,n*sizeof(int),10)<<endl;
cout<<"swar method "<<timeit(bitcountSWAR,(char*)a,n*sizeof(int),10)<<endl;
return 0;
}
统计bytearray中的bitcount的更多相关文章
- PHP array_count_values() 函数用于统计数组中所有值出现的次数。
定义和用法 array_count_values() 函数用于统计数组中所有值出现的次数. 本函数返回一个数组,其元素的键名是原数组的值,键值是该值在原数组中出现的次数. 语法 array_count ...
- 华为OJ平台——统计字符串中的大写字母
题目描述: 统计字符串中的大写字母的个数 输入: 一行字符串 输出: 字符串中大写字母的个数(当空串时输出0) 思路: 这一题很简单,直接判断字符串中的每一个字符即可,唯一要注意的一点是输入的字符串可 ...
- sort +awk+uniq 统计文件中出现次数最多的前10个单词
实例cat logt.log|sort -s -t '-' -k1n |awk '{print $1;}'|uniq -c|sort -k1nr|head -100 统计文件中出现次数最多的前10个单 ...
- c程序设计语言_习题1-13_统计输入中单词的长度,并且根据不同长度出现的次数绘制相应的直方图
Write a program to print a histogram of the lengths of words in its input. It is easy to draw the hi ...
- Java基础知识强化之集合框架笔记61:Map集合之统计字符串中每个字符出现的次数的案例
1. 首先我们看看统计字符串中每个字符出现的次数的案例图解: 2. 代码实现: (1)需求 :"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5) ...
- 学c语言做练习之统计文件中字符的个数
统计文件中字符的个数(采用命令行参数) #include<stdio.h> #include<stdlib.h> int main(int argc, char *argv[] ...
- 用SQL实现统计报表中的"小计"与"合计"的方法详解
本篇文章是对使用SQL实现统计报表中的"小计"与"合计"的方法进行了详细的分析介绍,需要的朋友参考下 客户提出需求,针对某一列分组加上小计,合计汇总.网上找 ...
- JAVA 统计字符串中中文,英文,数字,空格的个数
面试题:输入一行字符,分别统计出其中英文字母.中文字符.空格.数字和其它字符的个数 可以根据各种字符在Unicode字符编码表中的区间来进行判断,如数字为'0'~'9'之间,英文字母为'a'~'z'或 ...
- Python统计列表中的重复项出现的次数的方法
本文实例展示了Python统计列表中的重复项出现的次数的方法,是一个很实用的功能,适合Python初学者学习借鉴.具体方法如下:对一个列表,比如[1,2,2,2,2,3,3,3,4,4,4,4],现在 ...
随机推荐
- android 微信听筒无声
Dual talk项目sim卡插在卡2时.微信听筒无声: 第三方APP在听筒接听语音时会固定去设audio_mode为incall,而不会去管以下是sim1还是sim2在位. 而speechdrive ...
- iOS NSNotificationCenter 最基本使用
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:] , @"a ...
- ZH奶酪:PHP的cURL库
原文链接:http://coolshell.cn/articles/664.html 参考链接:http://www.runoob.com/php/php-ref-curl.html 使用PHP的cU ...
- 更新image的方法
1. 修改container 1.1 执行 docker images 查看目前的所有images: REPOSITORY TAG IMAGE ID ...
- Converter Standardalone 5 versus Converter Boot CD
The new Converter Standalone 5 lacks the Converter Boot CD. Fortunately you can still use the old ve ...
- js 数组 转为树形结构
题目: source = [{ id: 1, pid: 0, name: 'body' }, { id: 2, pid: 1, name: 'title' }, { id: 3, pid: 2, na ...
- 高仿美团主界面<一>
声明:本demo还未完好,正在持续更新中... 先上图吧: 这个小demo资源图片全是用青花瓷抠出来的,如今仅仅是完毕了 一部分. 会持续更行中. . .有兴趣的朋友能够关注我,我们一起coding, ...
- Android学习笔记九:Service
一:Service是什么 Service,服务.一般用于提供需要在后台长期运行的服务(如复杂计算.下载等等耗时任务),其特点是长生命周期的.没有用户界面.在后台运行的. 二:Service的生命周期方 ...
- ES6学习笔记十:模块的导入、导出
一:模块导入 1) import { 要导入的属性.方法民 } from '模块路径'; 2)该种方法需要有配置文件,指明模块所在路径 import { 要导入的属性.方法民 } from '模块名' ...
- Tomcat中的session实现
Tomcat中一个会话对应一个session,其实现类是StandardSession,查看源码,可以找到一个attributes成员属性,即存储session的数据结构,为ConcurrentHas ...