位运算总结以及空间换时间1

位总结:

1、位运算符号&,|,^,~(取反,不分正负数),<<(标准规定在右边补0),>>(正数则左边补0,负数标准没有规定在左边补充的数字,分为逻辑右移和算术右移,具体由编译器决定,windows平台和gcc采取算术右移即负数补1)
12 0000 1100
13 0000 1101
~12 1111 0011
12&13 0000 1100
12|13 0000 1101
12^13 0000 0001
12>>1 00000 110 6=12/2
12<<1 000 11000 24=12*2
2、常见的二进制位的变换操作
下面列举了一些常见的二进制位的变换操作。
去掉最后一位 | (101101->10110) |
在最后加一个0 | (101101->1011010) |
在最后加一个1 | (101101->1011011) |
把最后一位变成1 | (101100->101101) |
把最后一位变成0 | (101101->101100) |
最后一位取反 | (101101->101100) |
把右数第k位变成1 | (101001->101101,k=3) |
把右数第k位变成0 | (101101->101001,k=3) |
右数第k位取反 | (101001->101101,k=3) |
取末三位 | (1101101->101) |
取末k位 | (1101101->1101,k=4) |
取右数第k位 | (1101101->1,k=4) |
把右边连续的1变成0 | (100101111->100100000) |
把右起第一个0变成1 | (100101111->100111111) |
把右边连续的0变成1 | (11011000->11011111) |
去掉最后一位 | (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
最后一位取反 | (101101->101100) | x ^ 1
把右数第k位变成1 | (101001->101101,k=3) | x | (1 << (k-1))
把右数第k位变成0 | (101101->101001,k=3) | x & ~(1 << (k-1))
右数第k位取反 | (101001->101101,k=3) | x ^ (1 << (k-1))
取末三位 | (1101101->101) | x & 7
取末k位 | (1101101->1101,k=4) | x & ((1 << k)-1)
取右数第k位 | (1101101->1,k=4) | (x >> (k-1)) & 1
把右边连续的1变成0 | (100101111->100100000) | x & (x+1)
把右起第一个0变成1 | (100101111->100111111) | x | (x+1)
把右边连续的0变成1 | (11011000->11011111) | x | (x-1)
经典算法题1
1:有一些数字,每个数字都出现两次,只有一个数字出现一次,请找到它.例如1,5,4,2,3,3,2,1,5
算法1:排序是底线(快排的时间复杂度O(nlogn)),太慢了
算法2:用按位异或^ (相同的数字a^a为0) O(n)
2:有一些数字,每个数字都出现两次,只有两个个数字出现一次,请找到它们.例如1,5,4,2,3,3,6,2,1,5
算法:分组,每一组只有一个出现一次的数字,再用上面的算法2
改题算法思想:由于其中有两个数字不一样,那么异或的结果肯定不为0,所以在异或的结果中找到第一个1的位置n,然后将数组分为两组,第一组为n位置为1的一组,第二组n位置为0,各组按位异或即可得到答案。
下面为具体实现过程
在这里插入图片描述
经典算法题3
统计一个字节的数字中二进制1的个数.例如2->1,3->2
第一种办法:在这里插入图片描述

第二种方法:对ch的二进制进行遍历
在这里插入图片描述
第三种方法:
ch&=(ch-1);该表达式的意思为丢弃最右边的1;如果想不通,可以举几个例子实现一下过程就明白了
在这里插入图片描述
第四种方法:
该方法就是很明显的空间换时间,不过只能适用于数值比较小的情况
在这里插入图片描述