异或性质:相同为0,不同为1(无进位相加)
1.由于0^0=0 0^1=1 所以,0^任何数 = 任何数。
2.由于1^0=1 1^1 =0所以,1^任何数 = 任何数取反。
3.任何数^任何数 = 0。
4.用于将特定的位反转,如对10100001的第2位和第3位翻转,可以将数与00000110进行按位异或运算。
5.通过按位异或运算,可以实现两个值的交换,而不必使用临时变量。
6.异或运算的特点:a两次异或同一个数b(a=a ^ b ^ b)仍然为原值a。
7.异或是可交换的:a^b = b^a。
例1:不使用临时变量交换a和b的值。
a= 10100001
b= 00000111
a=a^b; //a=10100110
//此步操作是将a b原值的相同位记录为0,不同位记录为1.
//并保存在a中,b值此步并没有发生变化
//由于1^任何数 = 任何数取反 0^任何数 = 任何数
b=b^a; //b=10100001
//a中用1表示原值中对应位不同的部分
//做异或操作是将b中与(原a)中相同的部分保留,与(原a)中不同的部分取反
//即将b编程原来的a
a=a^b //a=00000111
//由于此时的a表示异同,b表示原来的a
//同理第二部步可获得原b值,赋给a即可实现转换
LeetCode——面试题 16.01. 交换数字
题目描述:
编写一个函数,不用临时变量,直接交换numbers = [a, b]中a与b的值。
提示:
numbers.length == 2
示例:
输入: numbers = [1,2]
输出: [2,1]
代码如下:
class Solution {
public:
vector<int> swapNumbers(vector<int>& numbers) {
numbers[0]=numbers[0]^numbers[1];
numbers[1]=numbers[0]^numbers[1];
numbers[0]=numbers[1]^numbers[0];
return numbers;
}
};
执行结果:
例2:
任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。
#include<iostream>
#include<vector>
using namespace std;
int main(){
int res = 0;
vector<int> v{
1,2,2,3,1,8,8 };
for (int i = 0; i < v.size() ; i++){
res ^= v[i];
cout << res << " ";
}
return 0;
}
例3:LeetCode——面试题 17.04. 消失的数字
题目描述:
数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
示例 1:
输入:[3,0,1]
输出:2
示例 2:
输入:[9,6,4,2,3,5,7,0,1]
输出:8
代码如下:
方法1:(使用异或,利用了特点6)
class Solution {
public:
int missingNumber(vector<int>& nums) {
int size=nums.size();
int ans=0;
for(int i=0;i<size;i++){
ans^=i;
ans^=nums[i];
}
ans^=size;
return ans;
}
};
方法二:(从0到n求和减去nums数组求和,即为缺失的数)
class Solution {
public:
int missingNumber(vector<int>& nums) {
int size=nums.size();
int sum1=0,sum2=0;
for(int i=0;i<size;i++){
sum1+=nums[i];
sum2+=i;
}
return sum2+size-sum1;
}
};
方法三:(直接找到那个缺失的数,但是时间复杂度超过了O(n),仅供参考)
class Solution {
public:
int missingNumber(vector<int>& nums) {
int size=nums.size();
int ans=-1;
sort(nums.begin(),nums.end());
for(int i=0;i<size;i++){
if(nums[i]!=i){
ans=i;
break;
}
}
if(ans==-1){
return size;
}
return ans;
}
};
执行结果:
例四:LeetCode——389. 找不同
题目描述:
给定两个字符串 s 和 t,它们只包含小写字母。
字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。
示例 1:
输入:s = “abcd”, t = “abcde”
输出:“e”
解释:‘e’ 是那个被添加的字母。
示例 2:
输入:s = “”, t = “y”
输出:“y”
示例 3:
输入:s = “a”, t = “aa”
输出:“a”
示例 4:
输入:s = “ae”, t = “aea”
输出:“a”
代码如下:
class Solution {
public:
char findTheDifference(string s, string t) {
char ch=0;
for(int i=0;i<s.size();i++){
ch^=s[i];
}
for(int j=0;j<t.size();j++){
ch^=t[j];
}
return ch;
}
};
执行结果: