位运算

引子:二进制中1的个数

      请实现一个函数,输入一个整数,输出该数二进制表示中的个数。例如把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2。

      此题容易进入一个误区:误认为输入的数一定是正数,于是我很快写出这样的代码:

 1 int num(int n)
 2 {
 3     int count=0;
 4     while(n)
 5     {
 6         if(n&1) count++;
 7         n=n>>1;
 8     }
 9     return count;
10 }

      看完书,发现自己落入了作者或者说面试官所设的圈套。如果输入的是-9,那么程序就会陷入死循环,因为移位前是个负数,符号位为1,移位后还要保证是负数,所以最高位还是设为1,一直做右移运算,最终变成0xFFFFFFFF,一直循环下去。

      好吧,既然有此题做为做引子,那么本文就好好学习一下编程中的位运算。

      其实位运算加起来也就5中运算:与、或、异或、左移和右移。
      (1)与、或和异或

 
与(&) 0&0=0 1&0=0 0&1=0 1&1=1
或(|) 0|0=0 1|0=1 0|1=1 1|1=1
异或(^) 0^0=0 1^0=1 0^1=1 1^1=0

      (2)左移和右移

      m<<n:就是把m左移n位,最左边n位丢弃,最右边补n位0;

00001010<<2=00101000

10001010<<3=01010000

      m>>n:分为两种情况,有符号数和无符号数。

                  无符号数:m右移n位,最右边n位丢弃,最左边补n位0;

0001010>>2=00000010

                  有符号数:m右移n位,最右边n位丢弃,最左边补n位1;如下面的8位有符号数右移:

10001010>>3=1110001

      

 

      好了,那么就找一些位运算题目做个练习。(13.09.04 update )

题目:求数组中的唯一重复元素

      一个数组中含有1001个元素,存放了1,2,3...,1000和一个重复数字。只有唯一一个数是重复的,其他均只出现一次。要求设计算法找出这个数字。要求:每个数组元素只能方位一次,不能使用辅助存储空间。

      简单的方法是先求出1-1000的和sum1,然后遍历数组求到数组所有元素之和sum2,相减即为重复的数。这个方法存在的问题是,若是数组很大,那么求和可能会溢出。

      这里呢,我们用位运算怎么做呢?我在《剑指offer》博文中写过“数组中只出现一次的数字”一题,用的就是异或运算求解,有兴趣的读者可以顺便看一下。本题思路一样,利用相同的数异或后为0这一思路,求得最后那个重复的数。

 1 int main()
 2 {
 3     int a[]={1,2,3,4,5,6,3};
 4 
 5     int t=0;
 6     int length =7;
 7     
 8     for(int i=0;i<length;i++)
 9     {
10         t^=i;
11         t^=a[i];
12     }
13     cout<<t<<endl;//输出t为3
14     return 0;
15 }

 

 

参考:

1.何海涛《剑指offer》

2.http://www.matrix67.com/blog/archives/264

posted @ 2013-08-31 22:55  七年之后  阅读(367)  评论(0编辑  收藏  举报