这两天的一些笔试题

迅雷的一道题目

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值