ACWing 73.数组中只出现一次的两个数

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。
请写程序找出这两个只出现一次的数字。
你可以假设这两个数字一定存在。

样例:

在这里插入图片描述

思路1

首先想到的是使用哈希表,统计每个数字出现的频数,最后再遍历哈希表,找出只出现一次的数字。这样的时间复杂度为O(n),空间复杂度为O(n)。问题解决。实现代码如下:

思路1代码

class Solution(object):
    def findNumsAppearOnce(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        dic = dict()
        res = []
        for i in nums:
            if i in dic:
                dic[i] += 1
            else:
                dic[i] = 1
        for key, val in dic.items():
            if val == 1:
                res.append(key)
        return res

思路2

若要求时间复杂度为O(n),空间复杂度为O(1),哈希表的方法就不能使用了。在LeetCode上,有大神提出了分组位运算的解法。
1、若数组中只存在一个只出现一次的数字,则将所有数字进行异或操作,最后的结果就是该只出现一次的数字,原因:a^b ^a = a ^ a ^ b = 0 ^ b = b(异或运算的交换律);
2、若数组中存在两个只出现一次的数字,若将所有数字进行异或操作,最后的结果为这两个数异或的结果,即 a ^ b ^ c ^ c = a ^ b;
3、若能将数组中的数分为两组,每组包含一个只出现一次的数字,相同的数分到同一组,则两组数分别进行异或操作,最后的到的数就是两个只出现一次的数。
4、但我们无法通过异或结果来获取那两个数。此时的难点在于,对两个不同数字的分组。此时我们要找到一个操作,让两个数字进行这个操作后,分为两组。最容易想到的就是 & 1 操作, 当我们对奇偶分组时,容易地想到 & 1,即用于判断最后一位二进制是否为 1来辨别奇偶。
5、通过 & 运算来判断一位数字不同即可分为两组,那么我们随便两个不同的数字至少也有一位不同吧!我们只需要找出那位不同的数字mask,即可完成分组( & mask )操作。
由于两个数异或的结果就是两个数数位不同结果的直观表现,所以我们可以通过异或后的结果去找 mask!所有的可行 mask 个数,都与异或后1的位数有关。为了操作方便,我们只去找最低位的mask。

此思路参考了LeetCode链接 这位大神的思路。

代码实现

class Solution:
    def singleNumbers(self, nums: List[int]) -> List[int]:
        k = 0
        for n in nums:
            k ^= n
        mask = 1
        while((k&mask) == 0):	# 找到最低位的mask
            mask <<= 1
        a = 0
        b = 0
        for n in nums:
        	# 利用&mask操作进行分组,统一规则下,相同的数分到同一组,不同的数分到不同组
            if ((n&mask) == 0):		
                a ^= n
            else:
                b ^= n
        return [a, b]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值