春暖花开
雪化了,花开了,春天来了
posts - 149,comments - 125,trackbacks - 0
这也是《程序员面试攻略》上的一道题,题目是这样的:
请编写一个函数,确定一个整数的计算机内部表示中有几个“1”。

思索了一下这个题目,我是这样考虑的,也学书上给出伪代码
count = 0;
while (这个整数不为0)
{
      如果这个整数对2求余的结果是1,则count加1;
     将这个整数向右移移位
}

代码写出来是这样的:
int numOnesInBinary(int num)
{
    
int count = 0;
    
while (num != 0)
    
{
        
if (num % 2 == 1)
            count
++;
        num 
= num>>1;
    }


    
return count;
}

看了一下书中的答案,的确比我简练很多。对于求余这个方法还是比较笨的。书中采用了逻辑与。

判断条件从“num%2 == 1”变成 “num&1 == 1”,从程序中更倾向与后者。
所以在分析问题的时候,要学会用逻辑“与、或、异或”进行判断。

到这一步,看似已经很完美了。但是书中又出奇的给了另一种解法。这种想法我真的没有想到。

想法的出发点是考虑一个数字减1时,它的二进制发生了什么变化。减1得到的结果是,从最低位的1到最低位都发生了翻转,其他高位保持不变。如果您对这个整数和减一后的结果进行AND操作,得到的新的数字与原来的整数相比,只有最后一个1变成0.

如果进行多次这样的操作,这个整数的值变为0。这样我们也就获得了这个数的计算机表示中“1”的个数。

int numOnesInBinary2(int num)
{
    
int count = 0;
    
while(num != 0)
    
{
        num 
= num & (num-1);
        count
++;
    }

    
return count;
}


第一方法的时间复杂度为o(n),第二种的时间复杂度为o(m),m为1的个数。

后记:
最近一周多,一直在做这本书上的编程题。一天3道,自己先尝试编写,运行成功后再与书上的解答进行对比。稍有几次略感比书上稍好些。但大多数情况还是效率差一些。想想原因,还是练得比较少。所以继续努力。多多积累,养成良好的思维习惯。

posted on 2009-07-28 15:56 Sandy 阅读(636) 评论(3)  编辑 收藏 引用 所属分类: 面试总结

FeedBack:
# re: “1”的个数
2009-08-02 08:21 | codespy
无分支版的你这个快,原理是递归求二进位相邻两位的和。  回复  更多评论
  
# re: “1”的个数
2009-08-02 08:23 | codespy
@codespy
无分支版的 比 你这个快,原理是递归求二进位相邻两位的和。  回复  更多评论
  
# re: “1”的个数
2009-08-04 11:42 | Sandy
@codespy

这个我还真的没有想到.
你说的是这种么?
int numOnesInBinary3(int num)
{
num = num - ((num >> 1) & 0x55555555);
num = (num & 0x33333333) + ((num >> 2) & 0x33333333);
num = (num+ (num >> 4)) & 0x0F0F0F0F;
num = num + (num >> 8);
num = num + (num >> 16);
return num & 0x0000003F;
}

我是在http://bvcat007.javaeye.com/blog/203577中看到的,原理是利用二分法,两两一组相加,之后四个四个一组相加,接着八个八个,最后就得到各位之和了。

他还提供了一种是
int numOnesInBinary4(int num)
{
unsigned n;
n = (num >> 1) & 033333333333;
num = num - n;
n = (n >> 1) & 033333333333;
num = num - n;
num = (num + (num >> 3)) & 030707070707;
num = num% 63;

return num;
}
首先是将二进制各位三个一组,求出每组中1的个数,然后相邻两组归并,得到六个一组的1的个数,最后很巧妙的用除63取余得到了结果。因为2^6 = 64,也就是说 x_0 + x_1 * 64 + x_2 * 64 * 64 = x_0 + x_1 + x_2 (mod 63),这里的等号表示同余。

  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理