(上級) 配列内の数値はすべて同じで、異なるのは 2 つだけであることがわかっているので、これら 2 つの数値を求めます。
ここでは 3 つのメソッドも提供されています。最初の 2 つは前のメソッドと似ており、3 つ目は XOR 演算の習熟が必要です。
解決策 1 (時間の複雑さが高い)
アイデア: for ループの 2 層。数値がそれ自体と同じ数値に到達しない場合は、その数値を記録します。それ以外の場合は、ループを終了し、次の番号のトラバースを続けます。
時間計算量: O( n 2 n^2n2 )
空間の複雑さ: O(1)
解決策 2 (空間の複雑性が高い)
アイデア: 辞書を使用します。辞書キーに数字が含まれていない場合は、その数字を辞書に追加します。そうでない場合は、キー値を削除します (任意の値、未使用)。最終的に、キー値は 2 つだけ残ります。これを出力します。 2 つのキー。
時間計算量: O(n)
空間計算量: O(n)
解決策 3 (最良)
アイデア: グループ化された XOR を使用します。前の質問よりも数値が 1 つ多いため、最初の XOR を 1 つずつ実行した後、これら 2 つの異なる数値の XOR 値しか取得できません。したがって、グループ XOR を実行し、2 つの異なる数値を 2 つのグループに分割し、それらを次々に XOR する必要があります。これは前の質問と同じになります。
スウィフトコード:
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)