萌新练习写代码的每日一练:只出现一次的数字III

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。

示例 :

输入: [1,2,1,3,2,5]
输出: [3,5]
注意:

结果输出的顺序并不重要,对于上面的例子, [5, 3] 也是正确答案。
你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?

思路:一开始想的是用暴力求解,虽然能做出来,但时间复杂度为O(N^2),超时了www,先列一下代码(其实不用列,但还是想记录一下自己的错误)

第一次的代码:

class Solution:
    def singleNumber(self, nums: List[int]) -> List[int]:
        res = []
        for i in range(len(nums)):
            temp = 0
            for j in range(len(nums)):
                if nums[i] == nums[j]:
                    temp = temp + 1
            if temp == 1:
                res.append(nums[i])

        return res

转换思路:建立字典并往里面存数,数量记为1,如果遇到重复的,数量+1,最后取key值为1的数

第二次的代码:

class Solution:
    def singleNumber(self, nums: List[int]) -> List[int]:
        count = {}
        res = []
        for num in nums:
            if num in count:
                count[num] += 1
            else:
                count[num] = 1
        for key in count:
            if count[key] == 1:
                res.append(key)
        return res

来一个奇葩的思路:用很神奇的XOR大法来做,题目要求是有两个数只出现一次,那么可以对他们进行一个分组,然后再用XOR去做,XOR指的是从数组第一个数开始,一直往后做异或操作,假设数组是[1,2,1,3,2],先是1^2

0x0001
0x0010 ^
—————
0x0011——>3

之后用上面得到的结果和1继续异或

然后 用上面的结果继续^1
0x0011
0x0001
————-
0x0010——>2

会发现结果变成了2,也就是说在刚才的操作中两个1互相抵消了,这样做可以说是消除了相同的数,继续做的结果得到的是3,也就是说这个数组里3只出现了一次。

不过既然题目说有两个数,那么需要对数组进行分组了,先用肉眼观察,题目样例中3和5只出现一次,那么可以对他俩进行异或操作

0x0011
0x0101 ^
————
0x0110——>6

这个表示的是3和5在二进制情况下的第二位和第三位(从右数)是不一样的,也就是说如果我们规定,第二位为0的放一组,第二位为1的放一组,就可以完美的将只出现一次的数字分开了(这个规定只是针对题目的例子)。

这时候定义一个函数lowbit,让他来求一个数出现1的最低位,例如样例中的3和5,lowbit(3,5)=2,然后判断其他数第二位是0还是1,只需要&2即可,比如说3

0x0011
0x0010 &
————
0x0010

这个第二位是1,放在第一组

再比如说1

比如1的话就是
0x0001
0x0010 &
————
0x0000

第二位是0,放在第二组

分好组之后再用XOR大法求解,完成!

奇葩思路的代码:

class Solution:
    def singleNumber(self, nums: List[int]) -> List[int]:
        res = [0, 0]
        xor = 0

        # 求目标数二进制出现1的最低位,用来分组
        def low_bit(num):
            return num & (-num)

        for num in nums:
            xor = xor ^ num

        lowbit = low_bit(xor)

        for num in nums:
            if lowbit & num == 0:
                res[0] = res[0] ^ num
            else:
                res[1] = res[1] ^ num
        return res

这个奇葩思路是一个学长提供的,他总是会给我整点新花样(逃

题目来自LeetCode第260题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值