欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

详解位运算解题套路

发布时间:2024/10/14 编程问答 27 豆豆
生活随笔 收集整理的这篇文章主要介绍了 详解位运算解题套路 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

1.位运算解题技巧

1、使用 x & 1 == 1 判断奇偶数。(注意,一些编辑器底层会把用%判断奇偶数的代码,自动优化成位运算)
2、不使用第三个数,交换两个数。x = x ^ y , y = x ^ y , x = x ^ y。(早些年喜欢问到,现在如果谁再问,大家会觉得很low)
3、两个相同的数异或的结果是 0,一个数和 0 异或的结果是它本身。(对于找数这块,异或往往有一些别样的用处。)
4、x & (x - 1) ,可以将最右边的 1 设置为 0。(这个技巧可以用来检测 2的幂,或者检测一个整数二进制中 1 的个数,又或者别人问你一个数变成另一个数其中改变了多少个bit位,统统都是它)
5、异或可以被当做无进位加法使用,与操作可以用来获取进位。
6、i+(~i)=-1,i 取反再与 i 相加,相当于把所有二进制位设为1,其十进制结果为-1。
7、对于int32而言,使用 n >> 31取得 n 的正负号。并且可以通过 (n ^ (n >> 31)) - (n >> 31) 来得到绝对值。(n为正,n >> 31 的所有位等于0。若n为负数,n >> 31 的所有位等于1,其值等于-1)
8、使用 (x ^ y) >= 0 来判断符号是否相同。(如果两个数都是正数,则二进制的第一位均为0,x ^ y=0;如果两个数都是负数,则二进制的第一位均为1;x ^ y=0 如果两个数符号相反,则二进制的第一位相反,x ^ y=1。有0的情况例外,^相同得0,不同得1)
9.a-b结果的符号(int 类型),可以用(a-b)>>31得出,-1则是为负,0为正数

2.异或(^)与与(&)左移(<<)做加法运算


无进位和 与 异或运算 规律相同,进位 和 与运算 规律相同

那么每异或一次,相当于求一次两数无进位和,每做一次与运算加左移,相当于求出所有进位的和,再与第一次异或的结果再次异或,如此循环,当没有进位时即进位和为0时,代表求出最终结果

C++代码

class Solution { public:int add(int a, int b) {while(b!=0){int c=(unsigned int)(a&b)<<1;a=a^b;b=c;}return a;} };

3.异或(^)的妙用



那么如果把一个数组的所有元素全部异或一遍,那么最终得到的结果是两个不重复值的异或结果,又由于异或是相同得0不同得1,我们找到异或结果从低位到高位的第个位1(哪一位1都无所谓),那么异或的两个值,一个此位置为0,一个此位置为1,就可以把数组的元素分为两组,这个时候,此位置为1的数据与a异或,为0的数据与b异或,最终a和b就是两个我们需要的数据(其余数据的异或会得到0,因为其余数字都出现两次)

class Solution { public:vector<int> singleNumbers(vector<int>& nums) {//用于将所有的数异或起来int k = 0;for (int num : nums) {k ^= num;}//获得k中最低位的1,K里面两数不同,故肯定有一位1是不同的,可以以此区分int mask = 1;while ((k & mask) == 0) {mask <<= 1;}int a = 0; int b = 0;for (int num : nums) {if ((num & mask) == 0) {a ^= num; // 找到那位不为1的元素, 其余数为偶数,会自动消去} else {b ^= num; // 找到那位为1的元素}}return {a, b};} };

4.0x55555555与0xaaaaaaaa的妙用

0xaaaaaaaa = 10101010101010101010101010101010 (偶数位为1,奇数位为0)
0x55555555 = 1010101010101010101010101010101 (偶数位为0,奇数位为1)

class Solution { public:int exchangeBits(int num) {int odd = num & 0x55555555;//偶数int even = num & 0xaaaaaaaa;odd = odd << 1;even = even >> 1;return odd | even;} };

5.n&(n-1)的妙用

任何一个是2的幂次方的数,它都是最高位(代表数值的位)是1,后面的数字全0,那么这个数减1与这个数进行位于运算一定为0,即:

class Solution { public:bool isPowerOfTwo(int n) {return (n>0)&&(n&(n-1))==0;} };

n&(n-1)每进行一轮都会把当前数值部分(也就是n)最低位的1变成0。比如:数值11转化成二进制有三个1,那么每进行一次n=n&(n-1)就会消去当前n最低位的1

class Solution { public:int hammingWeight(uint32_t n) {int cnt=0;while(n){n&=(n-1);++cnt;}return cnt; } };

总结

以上是生活随笔为你收集整理的详解位运算解题套路的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。