位操作(Bitwise Operation)是一种直接对整数的二进制位进行操作的计算方法。在计算机中,数据通常以二进制形式存储,位操作允许我们直接操作这些二进制位。位操作通常比常规的算术运算更高效,因为它们直接作用于二进制位而不涉及更复杂的计算。
常见的位操作符
1.按位与(&):
对应位都为1时,结果为1,否则为0。
例如:1010 & 1100 = 1000
2.按位或(|):
只要对应位有一个为1,结果就为1。
例如:1010 | 1100 = 1110
3.按位异或(^):
对应位不同,结果为1;相同,结果为0。
例如:1010 ^ 1100 = 0110
特点:任何数与0异或都不变,任何数与自己异或都变成0。
4.按位取反(~):
将每一位的0变成1,1变成0。
例如:~1010 = 0101(具体结果取决于机器字长)
5.左移(<<):
把一个数的二进制位全部向左移动若干位,右边补0。
例如:1010 << 2 = 101000(即乘以2的幂)
6.右移(>>):
把一个数的二进制位全部向右移动若干位,左边补0或符号位(符号位取决于是有符号右移还是无符号右移)。
例如:1010 >> 2 = 0010(即除以2的幂)
应用
位操作非常适合用来处理涉及二进制的场景,如:
权限控制: 使用位掩码(bitmask)来管理多个权限。
数据压缩: 通过位操作可以将多个小数据压缩到一个整数中。
加密与校验: 利用按位异或进行简单的加密和校验。
性能优化: 位操作常常比同等功能的常规操作更高效。
示例
例如在问题“找出数组中只出现一次的元素”中,我们使用了按位异或(^)操作的特性:
如果一个数在多个位置出现偶数次,经过多次异或后会被抵消为0。
唯一一个出现一次的数,不会被抵消掉,因此异或后结果就是这个数。
通过这些操作,我们能在高效的时间和空间复杂度下解决各种问题。
leetcode 137.链接只出现一次的数字
给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。
public class SingleNumber {
public int singleNumber(int[] nums) {
int ones = 0, twos = 0;
for (int num : nums) {
// 计算ones,当twos不包含num时,ones ^= num
ones = ones ^ num & ~twos;
// 计算twos,当ones不包含num时,twos ^= num
twos = twos ^ num & ~ones;
}
// ones就是只出现一次的数字
return ones;
}
public static void main(String[] args) {
SingleNumber solution = new SingleNumber();
int[] nums1 = {2, 2, 3, 2};
System.out.println(solution.singleNumber(nums1)); // 输出:3
int[] nums2 = {0, 1, 0, 1, 0, 1, 99};
System.out.println(solution.singleNumber(nums2)); // 输出:99
}
}
我看不懂,只能硬记