需求: 这个是刷题的时候看到的,很有意思,题目是:已知一个数组全是数字,只有一个数字只出现了一次,其他的都出现两次,怎么知道这个数字是多少(只需知道数字是几,不需要位置信息),比如数组 [1,2,3,4,5,1,2,3,4],我们需要求出只出现了一次的数字 5。
方法一:通过两层 for 循环遍历;
原理很简单,就是两层 for 循环找个没有重复出现的那个数(这个方法应该是最复杂的方法);
let arr = [1,2,3,4,5,1,2,3,4];
let getSingleNum = function(arr){
for(let i=0; i<arr.length; i++){
let flag = true;
for(let j=0; j<arr.length; j++){
if(arr[i]==arr[j]&&i!==j){
flag=false
}
}
if(flag){
return arr[i]
}
}
}
getSingleNum(arr) // 5
方法二:使用位运算符 异或(^)
异或,是一种位运算符,它会将数字转换成二进制进行计算,计算规则是:相同为0,不同为1,如 8^7,计算过程为: 1000 ^ 0111 结果就为 1111;所以,异或就有了以下特性:
1.0 异或任何数就等于该数本身,如 0 ^ 5 结果为 5 ;
2.两个相同的数异或的结果为0,如7 ^ 7 结果为0;
3.异或运算满足交换律和结合律,如 2 ^ 3 ^ 4 与 4 ^ 3 ^ 2 结果是一样的
所以就有了以下代码:
let arr = [1,2,3,4,5,1,2,3,4]
let getSingleNum = function(arr){
let num = 0
for(let i=0;i<arr.length;i++){
num = num ^ arr[i]
}
return num
}
getSingleNum(arr) // 5
扩展: 异或还有一个作用,可以用来判断一个数是否的2的n次方( n为正整数 ),当然,你也可以通过一直 %2 来实现,但是异或的方式更方便快捷
let isTwo =function(num){
return num^(num-1) === num + (num-1)
}
isTwo(4) // true
isTwo(3) // false
这个方法的原理也很简单,在二进制中,2的 n 次方为 1000000…(有n个0), 而2的n次方减一则为 0111111(有n个1),所以这两个数异或的结果就为 111111…(有n+1个1),这个数就为 2的n次方加上2的n次方减一。