1. 程式人生 > >統計bytearray中的bitcount

統計bytearray中的bitcount

AC 暴力 byte數組 基礎 詳細介紹 byte init 運算 ret

給定一個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