- 把数字转化为二进制表示后,对每一位的0或者1进行运算,比如与、或、异或、左移、右移等;
- 左移n位:丢弃最左边的n位,右边补n个0;
- 右移n位:丢弃最右边的n位,左边补符号位(无符号则补n个0,有符号则补n个1);
二进制中1的个数(剑指offer---面试题10)
题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制1001,有2位是1,因此如果输入9,该函数则输出2;
- int NumgerOf1(int n);
解题思路:
方法一:先判断整数n和1做与运算即可判断n的最右边一位是否为1,然后n右移一位,再判断n最右边一位是否为1,以此类推,直到该整数n变为0为止;
缺点:如果输入的整数n为负数,那么一直右移运算最终整数n会变成0xFFFFFFFF,即while死循环;
方法二:先将整数n和flag(初始值为1)做与运算即可判断n的最右边一位是否为1,然后将flag左移一位,再将n和flag做与运算,以此类推,直到flag变为0为止;
缺点:需要循环32次,即整数n二进制的位数;
解题思路:与运算即n & (n-1);
(1)假设整数n的二进制中最右边的1位于第m位,那么n-1后,第m位变成0,其之后的所有位都变成1;
(2)n和n-1做与运算后,相当于把n的二进制中的最右边的1变成0;
(3)以此类推,直到n变成0为止;
优点:有几个1就循环几次;
数组中只出现一次的数字(剑指offer---面试题40)
详情见“数组”专栏:异或;
不用加减乘除做加法(剑指offer---面试题47)
题目:写一个函数求两个整数之和,要求函数体内不得使用加减乘除的符号;
- int Add(int num1, int num2);
解题思路:异或和与;
(1)num1和num2求异或表示两个整数相加的和sum,但是没有计算进位;
(2)num1和num2求与后再左移一位表示两个整数相加后的进位carry;
(3)再次把sum和carry作为num1和num2,继续做相加运算,直到carry=0为止;
类似题目:不用加减乘除做两个整数的交换:a = a ^ b; b = a ^ b; a = a ^ b;
异或^的特点:a ^ a = 0; a ^ 0 = a;