整数をすばやく計算するバイナリ表現の1の個数
題目:1つの符号の32ビットの整数xを与えて、xのバイナリの表現法の中で1の個数を求めますか?
1つ目のアルゴリズム:
上のアルゴリズムの時間複雑度は1の個数である.
2番目のアルゴリズム(ルックアップ):
上記のアルゴリズムは最大4サイクルで,空間交換時間を用いる.
2番目のアルゴリズムの別の形式:
3つ目のアルゴリズム:
例えば、8ビットの整数122について、0111 1010(abcd efgh)をバイナリで表し、1行目のコードの機能はx=0 b 0 d 0 f 0 h+0 a 0 c 0 e 0 gであり、2桁の1組で、それぞれ4組(a,b;c,d;e,f;g,h;)のうち1の個数を計算し、この例ではx=101,000+0001 0101=0101(更新されたabcd efgh)であり、これに基づいて、さらにグループ化し、2行目の機能x=00 cd 00 gh+00 ab 00 ef,4桁の1組である(abcd;efgh)は、この例ではx=0100001+0001=0001=00011 0010(abcd efghを更新する)の2つのグループが1を含む個数をそれぞれ計算し、さらに8ビットのグループが、3行目に示すようにx=0000 efgh+0000 abcd=000100+000001=0000101=5であるため、この整数122は5つの1を含む.
本アルゴリズムの考え方:集計して、1つの32ビットの整数に対して、まず16グループに分けて、各グループ(2ビット)の中の1の個数を統計して、更に統計の結果を2つ合併して、8グループを得て、その上でまた合併して4グループ、2グループ、1グループを得て、更に最終結果を得ます.
1つ目のアルゴリズム:
int OneCount(unsigned int x)
{
for(int count=0; x>0; count++)
x&=x-1;// 1 0
return count;
}
上のアルゴリズムの時間複雑度は1の個数である.
2番目のアルゴリズム(ルックアップ):
const int idx[256]={0,1,1,,8}//0~255 1
int OneCount(unsigned int x)
{
int count=0;
for(; x>0; x>>=8)
count+=idx[x&255];
return count;
}
上記のアルゴリズムは最大4サイクルで,空間交換時間を用いる.
2番目のアルゴリズムの別の形式:
const int idx[256]={0,1,1,..,8}
int OneCount(unsigned int x)
{
unsigned char* p=(unsigned char*)&x;
return idx[*p]+idx[*(p+1)]+idx[*(p+2)]+idx[*(p+3)];
}
3つ目のアルゴリズム:
int OneCount(unsigned int x)
{
x=(x&0x55555555UL)+((x>>1)&0x55555555UL); //1
x=(x&0x33333333UL)+((x>>2)&0x33333333UL);//2
x=(x&0x0f0f0f0fUL)+((x>>4)&0x0f0f0f0fUL); //3
x=(x&0x00ff00ffUL)+((x>>8)&0x00ff00ffUL); //4
x=(x&0x0000ffffUL)+((x>>16)&0x0000ffffUL);//5
return x;
}
例えば、8ビットの整数122について、0111 1010(abcd efgh)をバイナリで表し、1行目のコードの機能はx=0 b 0 d 0 f 0 h+0 a 0 c 0 e 0 gであり、2桁の1組で、それぞれ4組(a,b;c,d;e,f;g,h;)のうち1の個数を計算し、この例ではx=101,000+0001 0101=0101(更新されたabcd efgh)であり、これに基づいて、さらにグループ化し、2行目の機能x=00 cd 00 gh+00 ab 00 ef,4桁の1組である(abcd;efgh)は、この例ではx=0100001+0001=0001=00011 0010(abcd efghを更新する)の2つのグループが1を含む個数をそれぞれ計算し、さらに8ビットのグループが、3行目に示すようにx=0000 efgh+0000 abcd=000100+000001=0000101=5であるため、この整数122は5つの1を含む.
本アルゴリズムの考え方:集計して、1つの32ビットの整数に対して、まず16グループに分けて、各グループ(2ビット)の中の1の個数を統計して、更に統計の結果を2つ合併して、8グループを得て、その上でまた合併して4グループ、2グループ、1グループを得て、更に最終結果を得ます.