逐步更新。。。
1.位操作符的运算优先级比较低,因此尽量使用括号来确保运算顺序,否则很可能会得到莫明其妙的结果。比如要得到像1,3,5,9这些2^i+1的数字。写成int a = 1 << i + 1;是不对的,程序会先执行i + 1,再执行左移操作。应该写成int a = (1 << i) + 1;
2.奇偶判断
for (i = 0; i < 100; ++i)//输出0~100内所有奇数
if (i & 1)
printf("%d ", i);
putchar('\n');
3.不用第三方变量交换两数
void Swap(int &a, int &b)
{
if (a != b)//这里是必须的,不然就会a^b==0,结果就是本来a、b用来交换的,经此函数操作后,都变成0了
{
a ^= b;
b ^= a;
a ^= b;
}
}
4.变换符号
取反加一
int sign_rev(int a){
return ~a+1;
}
5.求绝对值
int my_abs(int a)
{
int i=a>>31;//若a为正数,则i为0,若a为负数,则i为-1,0异或某数为某数,-1异或某数,等于某数取反
return (i^a)-i;
}
6.二进制逆序
第一步:每2位为一组,组内高低位交换
10 00 01 10 11 01 10 00
-->01 00 10 01 11 10 01 00
第二步:每4位为一组,组内高低位交换
0100 1001 1110 0100
-->0001 0110 1011 0001
第三步:每8位为一组,组内高低位交换
00010110 10110001
-->01100001 00011011
第四步:每16位为一组,组内高低位交换
01100001 00011011
-->00011011 01100001
#include <stdio.h>
void print(int a)
{
int i;
for(i=sizeof(a)*8-1;i>=0;--i)
{
if((a>>i)&1)
putchar('1');
else
putchar('0');
if(i%8==0)
putchar(' ');
}
putchar('\n');
}
int main(int argc, char *argv[])
{
unsigned int a=34520;
print(a);
a=((a&0xaaaaaaaa)>>1)|((a&0x55555555)<<1);
print(a);
a = ((a & 0xCCCCCCCC) >> 2) | ((a & 0x33333333) << 2);
print(a);
a = ((a & 0xF0F0F0F0) >> 4) | ((a & 0x0F0F0F0F) << 4);
print(a);
a = ((a & 0xFF00FF00) >> 8) | ((a & 0x00FF00FF) << 8);
print(a);
unsigned int b=0;
for(short int i=1;i!=0;i<<=1)
{
b<<=1;
if(a&1)
b|=1;
a>>=1;
}
print(b);
return 0;
}
7.二进制中1的个数
1)先写个衍生于树状数组中的做法:
int cnt=0;
while(b){
b-=(b&-b);
cnt++;
}
printf("cnt is %d\n",cnt);
不断减去二进制最后一个1,最后就能到一共减了几次,也就是有多少个1。其运算次数与输入n的大小无关,只与n中1的个数有关。如果n的二进制表示中有k个1,那么这个方法只需要循环k次即可
2)
速度不一定最快,但是想法绝对巧妙。 说一下其中奥妙,其实很简单,先将n写成二进制形式,然后相邻位相加,重复这个过程,直到只剩下一位。以217(11011001)为例,有图有真相,下面的图足以说明一切了。217的二进制表示中有5个1:
int BitCount4(unsigned int n)
{
n = (n &0x55555555) + ((n >>1) &0x55555555) ;
n = (n &0x33333333) + ((n >>2) &0x33333333) ;
n = (n &0x0f0f0f0f) + ((n >>4) &0x0f0f0f0f) ;
n = (n &0x00ff00ff) + ((n >>8) &0x00ff00ff) ;
n = (n &0x0000ffff) + ((n >>16) &0x0000ffff) ;
return n ;
}
8. 缺失的数字 LeetCode的那个single number
必定有一个数只出现一次而且其它数字都出现了偶数次。用搜索来做就没必要了,利用异或运算的两个特性——1.自己与自己异或结果为0,2.异或满足交换律。因此我们将这些数字全异或一遍,结果就一定是那个仅出现一个的那个数
const int MAXN = 15;
int data[MAXN] = {1, 347, 6, 9, 13, 65, 889, 712, 889, 347, 1, 9, 65, 13, 712};
int lostNum = 0;
for (int i = 0; i < MAXN; i++)
lostNum ^= data[i];
printf("缺失的数字为: %d\n", lostNum);