[LeetCode](面试题56 - I)数组中数字出现的次数

题目

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

示例 1:

输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]

示例 2:

输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]

限制:

  • 2 <= nums <= 10000

解题思路

两个相同的数异或为0,根据此原理,相继对原数组中的数进行异或运算,最终的结果就是那两个只出现1次的数字的异或结果,由于这两个数字不一样,那么结果二进制表示中至少有一位为1,我们在二进制表示的结果中,找到第一个出现1的位置,不妨记为第t位。现在我们以第t位是不是1将原数组分为两个子数组,第一个子数组中第t位都是1,第二个子数组中第t位都是0,那么这两个只出现1次的数字必定分到了不同的子数组中,而其他的出现2次的数字则根据第n位的数字是否为1分到相应的子数组中,最终两个子数组中分别含有一个只出现1次的数字,剩下的都是出现2次的数字,再对两个子数组进行异或运算可得到要求的数字。

复杂度分析:
时间复杂度:O(n),我们只需要遍历数组两次。
空间复杂度:O(1),只需要常数的空间存放若干变量。

代码

class Solution:
    def singleNumbers(self, nums: List[int]) -> List[int]:
        flag = 0
        for num in nums:
            flag ^= num
        k = 0
        while (flag&1)==0:
            k += 1
            flag >>= 1
        a, b = 0, 0
        for num in nums:
            if (num >> k)&1 != 0:
                a ^= num
            else:
                b ^= num
        return [a, b]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值