华为机试——找出数组中不同的两个数字

(进阶)已知数组中数字都两两相同,只有两个不同,找出这两个数字

这里也提供三种方法,前两种和之前相似,第三种需要熟练异或运算。

题解一(时间复杂度高)

思路:两层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)

猜你喜欢

转载自blog.csdn.net/weixin_44758107/article/details/127635990
今日推荐