統計bytearray中的bitcount
阿新 • • 發佈:2018-05-26
AC 暴力 byte數組 基礎 詳細介紹 byte init 運算 ret
首先兩兩一組分成16組,然後四四一組分成8組,八八一組分成4組,16、16一組分成兩組。
統計各個組內1的個數,然後歸並可以通過移位運算和加法運算實現。
給定一個byte數組,要求統計byte數組的bitcount,也就是byte數組中為1的位的個數。
Redis提供了位數組數據結構,位數組是相對獨立的一個程序,在《Redis設計與實現》(黃建宏著)一書中,對此有詳細介紹。
回到問題上來,看到這個問題的第一印象就是暴力。假設byte數組長度為n,那麽時間復雜度為8n。
我們的目的就是優化常數。
很容易想到的是用空間換時間,預先打表0~255之間的全部數字的bitcount,用到時直接查表,復雜度將為O(n).
這種方法的缺點在於只能存儲8位而不能存儲太多,因為隨著位數的增加,空間消耗指數級增長。
最高級的一種優化方法建立在位運算基礎上。這種方法的思想基於分治算法。
統計各個組內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