迅雷的一道題目
求\t\r\\t\0345\r字串的長度
http://hi.baidu.com/bshetlyijuaflxr/item/8e6585063386468b02ce1b99
http://hi.baidu.com/bshetlyijuaflxr/item/8e6585063386468b02ce1b99
判斷32位整數中1個數的演算法
這個問題看過很多遍了,有的時候覺得是顯而易見的,但是其實根本就沒完全明白。。
方法一:
int func(int n)
{
int count = 0;
while(n>0)
n&=(n-1),count++;
return count;
}
這個演算法的每一次迴圈將會去掉最右邊的一個1,直到n為0!
方法二:
unsigned int func(unsigned int x)
{
x = (x & 0x55555555UL) + ((x >> 1) & 0x55555555UL); // 0-2 in 2 bits
x = (x & 0x33333333UL) + ((x >> 2) & 0x33333333UL); // 0-4 in 4 bits
#if 1
// Version 1
x = (x & 0x0f0f0f0fUL) + ((x >> 4) & 0x0f0f0f0fUL); // 0-8 in 8 bits
x = (x & 0x00ff00ffUL) + ((x >> 8) & 0x00ff00ffUL); // 0-16 in 16 bits
x = (x & 0x0000ffffUL) + ((x >> 16) & 0x0000ffffUL); // 0-31 in 32 bits
return x;
#else
// Version 2
x = (x + (x >> 4)) & 0x0f0f0f0fUL; // 0-8 in 4 bits
x += x >> 8; // 0-16 in 8 bits
x += x >> 16; // 0-32 in 8 bits
return x & 0xff;
#endif
}
這個演算法理解起來很難,想了好長時間,計算1的個數是利用二分的方法,將所有位元遞迴相加,可以看到,首先是偶數位元和奇數位元相加,如果1的位元組在最後兩個位元上的話,那麼這就足夠計算1的個數了,但實際上高位可能存在1,所以將這個過程持續下去,第二次就將相鄰兩個位元組成一個組,同樣將奇數組和偶數組相加,這樣下去,所有高位的計數最後就合并到低位計數上了。
+---+---+---+---+---+---+---+---+
| 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | <---原數
+---+---+---+---+---+---+---+---+
| 1 0 | 0 1 | 0 0 | 1 0 | <---第一次運算後
+-------+-------+-------+-------+
| 0 0 1 1 | 0 0 1 0 | <---第二次運算後
+---------------+---------------+
| 0 0 0 0 0 1 0 1 | <---第三次運算後,得數為5
+-------------------------------+
整個程式是一個分治的思想。第一次我們把每相鄰的兩位加起來,得到每兩位裡1的個數,比如前兩位10就表示原數的前兩位有2個1。第二次我們繼續兩兩相加,10+01=11,00+10=10,得到的結果是00110010,它表示原數前4位有3個1,末4位有2個1。最後一次我們把0011和0010加起來,得到的就是整個二進位中1的個數。程式中巧妙地使用取位和右移,比如第二行中$33333333的二進位為00110011001100....,用它和x做and運算就相當於以2為單位間隔取數。shr的作用就是讓加法運算的相同數位對齊。