题目链接
前置知识
-
AND运算(按位与) : 二进制每位进行比较, 同时为1才为1, 其他情况均为0
- 6 & 3 == 110 & 011 = 010
-
OR运算(按位或) : 二进制每位进行比较,同时为0才为0, 其他情况全为1
- 6 & 3 == 110 | 011 = 111
-
XOR运算(按位异或) : 二进制每位进行比较, 不同时为1, 相同时为0
- 6 & 3 == 110 ^ 011 = 101
-
左移(<<) 将数字的二进制数往左移一位, 11变成110 等价于乘以2
-
右移(>>) 将数字的二进制数往右移一位, 111变成011 等价于除以2
先来几个简单的位运算小技巧热热手:
-
如何得到一个数的二进制最低位? 比如2,二进制表示位10, 如何得到最低为1
- 通过AND性质, 我们让2 和 1进行AND运算,
- 即 10 & 01 得到 0; 3 == 011 & 001 = 1
- 不管多少位,1都是n-1位0 + 1 只会对最后位产生影响
-
如何得到一个数的最低两位? n位?
- 同理, 两位只需要AND上3(11)即可, n位AND上
-
如何统计一个数中二进制位为1的数量?
- 考虑第1个问题是如何判断最低位,我们只需要让数字每次移除最低位进行判断,知道数字为0即可
- while(x) cnt += x & 1; x >>= 1
解题思路
-
简化题意: 是否存在[l,r]区间内XOR=2的数字对
-
考虑两个数XOR等于2, 2 == 10 前面添任意个0不会对值造成影响
-
那么这两个数的前面n-2位必须保证相同,(XOR性质,相同才为0)
-
比如当前数是7 我们要找一个数x 满足 7 XOR x == 2, 我们交换一下即 7 XOR 2 == x
-
答案显而易见 111 XOR 010 == 101 =5 我们只需要判断5是否在[l,r]区间内
代码
int solution(int L, int R) {
for(int i= L; i <= R; i++) {
int v = i ^ 2;
if(v >= L && v <= R) {
return 1;
}
}
return 0;
}
进阶
考虑算出区间内所有的XOR = 2 的数字对
- 很简单,只需要在上面代码的基础上加上一个记录的数据结构,确保不重复计算即可
- 比如 5 找到了 7 ,那么到7的时候就会再次找到5,set map都行
考虑算出区间内所有XOR = n的数字对
- 只需要把 nums ^ 2 改为 nums ^ x 即可