位运算的概念
位运算分为两大类:逻辑位运算符和位运算符
逻辑位运算又分为:位与(&),位或(|),异或(^),按位取反(~)
位运算符分为:左移(<<),右移(>>)
位与(&):二元运算符。两个数进行&运算,可以将其先转化为2进制数,然后从低到高&运算,对于每个位来说,只有两个都为1才为1,否则为0,再转化为十进制数,就是结果。
位或(|):二元运算符。两个数转换为二进制数,然后从低到高进行位或,对于每个位来说,只有两个都为0才为0,否则为1,再将其转换为十进制数就是结果。
异或(^):二元运算符。两个数转换为二进制数,然后从低到高进行位或,对于每个位来说,只有两个数不同的时候为1,否则为0,再将其转换为十进制数就是结果。
按位取反(~):一元运算符。当前数字转换成二进制后,所有的数1变0,0变1。
左移(<<):二元运算符。比如
x
<
<
y
x << y
x<<y表示
x
x
x左移
y
y
y位。就是将
x
x
x转换成二进制后,然后对它的所有位向左偏移
y
y
y位。末尾补0,所以如果左移一位可以看成将
x
x
x乘2。
右移(>>):二元运算符。比如
x
>
>
y
x >> y
x>>y表示
x
x
x右移
y
y
y位。就是将
x
x
x转换成二进制后,然后对它的所有位向右偏移
y
y
y位。如果
x
x
x是非负数则高位补0,如果是负数则高位补1。所以如果右移一位可以看成将
x
x
x除2,并且向下取整
异或的性质:相同的数异或为0,0与任何数异或为他本身,并且满足交换律和结合律。
4的幂一定时候2的幂,2的幂不一定是4的幂。当2的偶数次幂 2 2 x 2^{2x} 22x%3=1,2的奇数次幂 2 2 x + 1 2^{2x+1} 22x+1%3=2,所以只要在2次幂的基础上加上模3为1即可。
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int num = 0;
while(n != 0){
n &= n - 1;
num++;
}
return num;
}
}
//使用 n & 1 得到二进制末尾是否为 1;
//n & (n−1),其运算结果恰为把 nn 的二进制位中的最低位的 11 变为 00 之后的结果。
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int num = 0;
for(int i = 0; i < 32; ++i){
if((n & (1 << i) ) != 0){
num++;
}
}
return num;
}
}
//左移运算符(<<)用来将一个数的各二进制位全部左移若干位,移动的位数由右操作数指定,右操作数必须是非负值,其右边空出的位用0填补,高位左移溢出则舍弃该高位
class Solution {
public int rangeBitwiseAnd(int left, int right) {
while(left < right){
right &= right - 1;
}
return right;
}
}
//通过清除最低位的1,来获取计算两个二进制字符串的公共前缀
461. 汉明距离
^运算:只有两个1之间异或才是1。
class Solution {
public int hammingDistance(int x, int y) {
int z = x ^ y;
int s = 0;
while(z != 0){
z &= z - 1;
s++;
}
return s;
}
}
//求两个位运算合起来的1的数量
// ^ 参加运算的两个数据,按二进制位进行“异或”运算。
//两数异或运算,每次看最低位是不是1,
class Solution {
public int hammingDistance(int x, int y) {
int s = x ^ y, res= 0;
while (s != 0) {
res+= s & 1;
s >>= 1;
}
return res;
}
}
class Solution {
public int singleNumber(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
//将其存入哈希表中:若该元素不存在则存入表中,并计数为1,若已经存在获取次数并加1.
for(int i = 0; i < nums.length; ++i){
int x = map.getOrDefault(nums[i], 0);
map.put(nums[i], x + 1);
}
//遍历出出现次数为1的情况
//这时候使用keySet()方法获取所有的key值
for (int i : map.keySet()) {
if(map.get(i) == 1){
return i;
}
}
return 0;
}
}
/*Map.getOrDefault(Object key, V defaultValue)方法的作用是:
当Map集合中有这个key时,就使用这个key值;
如果没有就使用默认值defaultValue。
*/