(进阶)已知数组中数字都两两相同,只有两个不同,找出这两个数字
这里也提供三种方法,前两种和之前相似,第三种需要熟练异或运算。
题解一(时间复杂度高)
思路:两层for循环,如果一个数没有遍历到与自己相同的数,则记录这个数。否则,结束循环,换下一个数继续遍历。
时间复杂度:O( n 2 n^2 n2)
空间复杂度:O(1)
题解二(空间复杂度高)
思路:使用字典,如果字典key中不包含该数字,则添加到字典中,否则移除该key-value(任意值,用不到),最后字典中仅剩下两个key-value,输出这两个key。
时间复杂度:O(n)
空间复杂度:O(n)
题解三(最优)
思路:使用分组异或。由于比上个题目又多了一个数字,所以在第一次逐个异或之后,只能得到这两个不同数字的异或值。所以,我们还需要进行分组异或,将两个不同的数分成两组,再依次异或就和上个题目一样了。
swift代码:
func findDifferentTwoNum(_ array: [Int]) -> [Int] {
var res = Array<Int>() //存放结果的数组
var tmp = 0 //第一次数组逐个异或的结果,最终结果为:唯一两个不同数的异或值
var rightMove = 0 //为了将两个不同数进行分组,找到tmp哪一位为1(异或值不同为1,说明这两个数在这一位不相同)
var num1 = 0 //两个不同数其中一个
var num2 = 0 //两个不同数另一个
/**
第一次数组逐个异或的结果
最终结果tmp为:唯一两个不同数的异或值
*/
for i in 0..<array.count{
tmp = tmp ^ array[i]
}
/**
tmp逐次右移
找到tmp哪一位为1
异或为1,说明那两个不同的数在该位上不相同,以此作为区分,将两个不同的数分到不同的组中去
例如:rightMove:1 说明tmp右移一位,两个不同的数在第二位出现不同
*/
while((tmp & 1) == 0){
tmp = tmp >> 1
rightMove += 1
}
/**
((array[i] >> rightMove) & 1)来进行分组,这两个不同的数结果一个为0,一个为1
*/
for i in 0..<array.count{
if(((array[i] >> rightMove) & 1) == 1){
num1 = num1 ^ array[i]
}else{
num2 = num2 ^ array[i]
}
}
/*
最后分离出两个数
*/
res.append(num1)
res.append(num2)
return res
}
时间复杂度:O(n)
空间复杂度:O(1)