目录
传送门
知识点
位异或运算符 ^ a ^ b
运算规则
0^0=0,1^0=1,0^1=1,1^1=0(同为0,异为1)
例如:
3 ^ 7 = 0000 0011 14 ^ 1 = 0000 1110
| 0000 0111 | 0000 0001
= 0000 0100 = 0000 1111
= 4 = 15
常用知识点
交换律:a ^ b ^ c <=> 情况a ^ c ^ b
任何数于0异或为任何数 0 ^ n = n
相同的数异或为0: n ^ n = 0
异或运算符的应用
1、标记位取反
例:给定数 x ,返回 x 的第 4 位(从左到右)取反后的数
int f(int x){
return x ^= 0b1000;
}
2、交换变量
例:给定两个数,交换其值
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) {
a = a ^ b; // a = a ^ b
b = a ^ b; // b = a ^ b = (a^b)^b = a ^ 0 = a
a = a ^ b; // a = a ^ b = (a^b)^a = b ^ 0 = b
printf("%d %d\n", a, b);
}
return 0;
}
课后习题
简单题我重拳出击!!!!!!!!!!!!!!
136.只出现一次的数字
136. 只出现一次的数字https://leetcode-cn.com/problems/single-number/
题目描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
思路:因为 n ^ n = 0; 0 ^ n = n。所有异或所有的数字,出现两次次的异或都为 0,最后与出现一次的数字异或
int singleNumber(int* nums, int numsSize){
int ans = 0,i;
for(i=0; i<numsSize; ++i){
ans ^= nums[i]; // n^n = 0 且 n^0 = n
}
return ans;
}
190. 颠倒二进制位
190. 颠倒二进制位https://leetcode-cn.com/problems/reverse-bits/
题目描述:
颠倒给定的 32 位无符号整数的二进制位。
思路:倒过来取位,设定位
int GetBit(int x,int i){
return (x>>i) & 1;
}
void SetBit(int *x,int i,int v){
*x |= ((long)v<<i);
}
uint32_t reverseBits(uint32_t n) {
uint32_t ret = 0;
int i;
for(i=0; i<=31; ++i){
int v = GetBit(n,31-i); //颠倒过来取位
SetBit(&ret,i,v); //设定位
}
return ret;
}
461. 汉明距离
461. 汉明距离https://leetcode-cn.com/problems/hamming-distance/
题目描述:
两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。
给你两个整数
x
和y
,计算并返回它们之间的汉明距离。思路:先异或,再统计1的个数
int hammingDistance(int x, int y){
x ^= y; //异或运算 不同的位则会置1
int ans = 0;
while(x){
++ans;
x = x & (x-1); //每次将最低位 的1消去
}
return ans;
}
1486. 数组异或操作
1486. 数组异或操作https://leetcode-cn.com/problems/xor-operation-in-an-array/
题目描述:
给你两个整数,n 和 start 。
数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length 。
请返回 nums 中所有元素按位异或(XOR)后得到的结果。
int xorOperation(int n, int start){
int ans = 0;
for(int i=0;i<n;++i)
ans ^= (start + 2*i); //直接按题目要求来就行了
return ans;
}
477. 汉民距离总和
477. 汉明距离总和https://leetcode-cn.com/problems/total-hamming-distance/
题目描述:
两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。
给你一个整数数组
nums
,请你计算并返回nums
中任意两个数之间 汉明距离的总和 。在力扣找的一个解释
思路是: 比如有3个数(用二进制表示) (方向从右到左<-,分别为第1位、第2位...) 第一个数 a: 1 0 0 1 第二个数 b: 0 1 1 1 第三个数 c: 0 0 1 1 那么第一位上的汉明距离总和是0。 为什么? 因为a、b、c该位全是"1",任意两个"1"的汉明距离是0,所以该位汉明距离总和是0。 接下来看第二位,a的第二位是"0",b、c的是"1",此时该位的汉明距离就是2。 为什么? 由上面我们可以得到,该位的"0"有1个,"1"有2个,而任意一个"0"都可以和任意一个"1"组合, 一对组合可以产生的汉明距离为1,所以问题转换为了算多少对01组合,那么怎么计算呢? 答案就是该位"0"的个数乘以"1"的个数。 接下来看第三位,可以看出,此时"0"有2个,"1"有1个,所以可以产生的汉明距离为2。 接下来看第四位,可以看出,此时"0"有2个,"1"有1个,所以可以产生的汉明距离为2。 于是: 总的汉明距离就是 0 + 2 + 2 + 2 = 6 */
int GitBit(int x,int i){
return (x >> i) & 1; //取位
}
int bits[32][2];
int totalHammingDistance(int* nums, int numsSize){
int ret = 0,i,j;
for(i=0; i<=31; ++i)
bits[i][0] = bits[i][1] = 0; //初始化
for(i=0; i<numsSize; ++i){
for(j=0; j<=31; ++j){
int temp = GitBit(nums[i],j);
++bits[j][temp]; //统计每个位上的 0 和 1 的个数
}
}
int ans = 0;
for(i=0; i<=31; ++i){
ans += (bits[i][0] * bits[i][1]);
}
return ans;
}
1720. 解码异或后的数组
1720. 解码异或后的数组https://leetcode-cn.com/problems/decode-xored-array/
题目描述:
未知 整数数组 arr 由 n 个非负整数组成。
经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3] 。
给你编码后的数组 encoded 和原数组 arr 的第一个元素 first(arr[0])。
请解码返回原数组 arr 。可以证明答案存在并且是唯一的。
思路:
看着这题感觉这定义好熟悉,总感觉和Gray码和二进制码转换一个意思
a^b = c , a^b^b = a, 即 c^b=a 同理 c^a =b
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* decode(int* encoded, int encodedSize, int first, int* returnSize){
int *ans = (int*)malloc(sizeof(int)*(encodedSize+1));
*returnSize = encodedSize+1;
ans[0] = first; //第一个元素first
for(int i=1;i<encodedSize+1;++i){
ans[i] = ans[i-1] ^ encoded[i-1];
}
return ans;
}