这两天的一些笔试题

来源:互联网 发布:中美贸易逆差数据 编辑:程序博客网 时间:2024/06/05 17:24

迅雷的一道题目

求\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的作用就是让加法运算的相同数位对齐。

原创粉丝点击