1.位运算符
位运算:针对二进制(数字本来int,4字节,下面假设为1字节)
12:0000 1100
13:0000 1101
- 按位取反 :~12:1111 0011
- 按位与,相同的位都为1才为1 :12&13:0000 1100
- 按位或,相同的位只要有1就为1:12 | 13:0000 1101
- 按位异或,相同的位不一样就为1:12^13:0000 0001
- 按位左移,右边补0(离符号太远):12<<1:000 11000,24=12*2 左移相当于乘法(正数) 乘以2的位移次方。
- 按位右移,左边补符号位(如果是无符号数补0,有符号数符号位为0则补0,为1则补1):12>>1:00000 110,6=12/2 右移相当于除法(正数),除以2的位移次方
2.利用位运算符构造新的数字
- 某位变1:x|其它位是0,当前位是1
- 某位变0:x&其它位是1,当前位是0
- 某位取反:x^其它位是0,当前位是1
举例
- 去掉最后一位 | (101101->10110) | x>>1
- 在最后加一个0 | (101101->1011010) | x<<1
- 在最后加一个1 | (101101->1011011) | (x<<1) | 1
- 把最后一位变成1 | (101100->101101) | x|1
- 把最后一位变成0 | (101101->101100) | (x>>1) <<1 x&~1
- 最后一位取反 | (101101->101100) | x^1
- 把右数第k位变成1 | (101001->101101,k=3) | x|(1<<(k-1))
- 把右数第k位变成0 | (101101->101001,k=3) | x&111011 -> x&~(1<<(k-1))
- 右数第k位取反 | (101001->101101,k=3) | x^100 -> x^(1<<(k-1))
- 取最右边的1位 | (1101101->1) | x&1 , x%2
- 取末三位 | (1101101->101) | x&111->x&((1<<3)-1) ,x&7
- 取末k位 | (1101101->1101,k=4) | x&((1<<k)-1)
- 取右数第k位 | (1101101->1,k=4) | (x>>(k-1))&1
编程
1:
所有的数字成对
,
只有一个数字只出现一次
,
找到它 。
//1^3^5^3^1=1^1^3^3^5=5
//找单的数字
int SingleNum(int* arr, int len)//O(n)
{
int tmp = 0;
for (int i = 0; i < len; i++)
tmp ^= arr[i];
return tmp;
}
int main()
{
int arr[] = {1,5,3,7,9,6,1,3,9,6,5};//所有的数字成对,只有一个数字只出现一次,找到它
//算法1:1.排序;2.遍历 O(nlogn)
//算法2:从头到尾按位异或(按位异或相同的数字为0,5^5==0)
int n = SingleNum(arr,sizeof(arr)/sizeof(arr[0]));
printf("%d\n",n);
return 0;
}