已知一个数组全为数字,且只有一个只有一项,其他的都是两项,如何找出那个只出现了一次的数字

需求: 这个是刷题的时候看到的,很有意思,题目是:已知一个数组全是数字,只有一个数字只出现了一次,其他的都出现两次,怎么知道这个数字是多少(只需知道数字是几,不需要位置信息),比如数组 [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次方减一。

猜你喜欢

转载自blog.csdn.net/brilliantSt/article/details/123215653