持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
程序中的所有数在计算中都是以二进制的形式存储的,位运算实际就是直接对整数在内存中的二进制位进行操作。由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快。
运算规则
| 符号 | 描述 | 运算规则 |
|---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
l | 或 | 两个位都为0时,结果才为0 |
^ | 异或 | 相异为1,相同为0 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 各二进制全部左移若干位,高位丢弃,低位补0,a<<b,表示a左移b位; |
>> | 右移 | 各二进制全部右移若干位,对于无符号数,高位补0,低位丢弃 |
ps:这里用 | 表示或显示不出来,就用字母l代替了...
XOR 异或
异或:相同为0,相异为1。
几个特点:
| 运算 | 解释 |
|---|---|
x ^ 0 = x | x中的每个0与0异或结果是0,每个1与0异或结果是1,所以x和0异或的结果依旧是x本身 |
x ^ x = 0 | x与自己本身做异或,表示每一个位异或的对象都是相同的值,相同值异或的结果当然是0 |
x^1s = ~x // 1s=~0 | x中的每个0与1异或结果是1,每个1与1异或结果是0,所以相当于是将x的每一位都取反了,即等于~x |
x^(~x) = 1s | x异或取反的x,表示每一位的异或都是不同的值,即结果返回1s |
a^b=c => a^c=b, b^c=a | 异或满足交换律,从前面的例子中也可以得出该结论 |
a^b^c=a^(b^c)=(a^b)^c | 满足结合律 |
注:1s 表示多个位的1,s是x位的长度
实战中常用的位运算
1. x&1=1,表示x是奇数。
解释:x与1进行与运算,相当于是把x的最后一位跟1做与运算,因为x的高位跟1相与结果都是0,那么只要看x的最低位是0还是1就可以了,以下面为例。
- 2&1 ==> 0010 & 0001 = 0000
- 6&1 ==> 0110 & 0001 = 0000
- 3&1 ==> 0011 & 0001 = 0001
- 7&1 ==> 0111 & 0001 = 0001
可以看到高位的相与都是0,是没意义的,只要看最后一位与的结果就可以知道奇偶性了。奇数的最后一位必是1
2. x&(x-1) 可以清除x最低位的1
解释:
- 10 & 9 ==> 1010 & 1001 = 1000
3. x&-x 可以得到最低为的1
解释:-x可以理解为对x取反再加1,即等于~x + 1。
应用
- 权限判断
- 字符串包含判断
权限判断
略。
字符串包含判断
题目:剑指 Offer II 005. 单词长度的最大乘积
给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。
示例:
输入: words = ["abcw","baz","foo","bar","fxyz","abcdef"]
输出: 16
解释: 这两个单词为 "abcw", "fxyz"。它们不包含相同字符,且长度的乘积最大。
根据题意,需要判断两个单词是否包含相同的字符,可通过位掩码进行判断。设mask[i] 为第i个单词的位掩码,那么当两者有相同字符时,那么 mask[i] & mask[j] == mask[j] 。两个相同字符相与,也即相同值相与肯定是他们本身。反过来想,若没有相同字符,每个位都不同,那么相与的结果就是0。
如何将字符改为位运算相与呢?我们可以通过将字符转换为二进制码,放到mask数组中。然后用mask数组进行与运算判断长度乘积即可。
class Solution {
public int maxProduct(String[] words) {
int max = 0;
int[] mask = new int[words.length];
for(int i=0;i<words.length;i++) {
int n = words[i].length();
for(int j=0;j<n;j++) {
mask[i] |= 1<<(words[i].charAt(j) - 'a');
}
}
for(int i=0;i<words.length;i++) {
for(int j=i+1;j<words.length;j++) {
if( (mask[i] & mask[j]) == 0) { // 无交集
max = Math.max(max,words[i].length() * words[j].length());
}
}
}
return max;
}
}