序言
今天在leetcode上遇到一个题目-只出现一次的数字。具体的信息如下:
我看到题目后其实是有解法的,但是它隐晦的提醒了我不要定义数组来标记每个元素的出现,时间复杂也只能为O(n)也就是只能用一重循环。我想了很久也没有什么好的方法,于是我就去看了评论区大佬的解法。大佬的代码非常简单,一个循环每个元素都做按位异或运算,然后没了。从这里我就意识到我对位运算还不够了解,位运算虽然在我平时的代码中很少用到,但是它一定很重要,于是我整理了一些关于位运算的知识如下。
位运算
什么是位运算?
程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作。比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算。举个例子,6的二进制是110,11的二进制是1011,那么6 and 11的结果就是2,它是二进制对应位进行逻辑运算的结果(0表示False,1表示True,空位都当0处理)
由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度 非常快。
1)&
位与运算符为` &`,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0。
实际应用
1)判断奇偶性
由于奇数的二进制最后一位必定是1,而偶数最后一位是0,那么一个数n要判断它的奇偶性,就只要让它与1做位与运算就行了,结果为1则为奇数,结果为0,则为偶数
2)|
位或运算符为` |`,其运算规则是:参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1;如果对应的二进制位都为 0,结果才为 0。
3)^
位异或运算符为`^`,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。
结论:
1)任何一个整数与0进行异或运算后依然保持不变。
2)任何一个整数与-1进行异或运算后再加上1,得到的结果就是这个数的相反数。
3)相同数异或等于0
4)异或的交换律,异或顺序改变结果不变
实际应用
1)交换两个整数的值
2)判断两个整数是否相等
如果两个数相同,那么他们对应的二进制位相同,那么它们的按位异或结果应为0
4)~
位取反运算符为`~`,其运算规则是:只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。
实际应用
1)求相反值
例如:6的相反值为 ~6+1
5)>>
右位移运算符为` »`,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。
对于整数而言右移一位相当于除2
6)<<
左移位运算符为` «`,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
对于整数而言,左移一位相当于乘2
总结
位运算虽然运算效率高,但是代码的可读性会下降,所以在日常的开发中用到的不多,大多数使用还是在底层中,如jdk的实现就大量使用到了它。不过当你需要提高你代码的运行效率或解决一些特殊问题时一定不要忘记它。