leetcode -- single number 只出现一次的数字

136

给定一个整数数组,除了某个元素外其余元素均出现两次。请找出这个只出现一次的元素。

备注:
你的算法应该是一个线性时间复杂度。 你可以不用额外空间来实现它吗?

解析:不能用额外空间,所以哈希表也就是字典是不能用了,那就只能位操作了,用异或运算,a^a=0,所以出现两次的数都就消除了,最后剩下那个只出现一次的数

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        rst = nums[0]
        for i in range(1,len(nums)):
            rst = rst ^ nums[i]
        return rst

137

给定一个整型数组,除了一个元素只出现一次外,其余每个元素都出现了三次。求出那个只出现一次的数。

注意:
你的算法应该具有线性的时间复杂度。你能否不使用额外的内存来实现?

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        ones, twos = 0, 0
        for i in range(len(nums)):
            ones = (ones ^ nums[i]) & (~twos)
            twos = (twos ^ nums[i]) & (~ones)
        return ones

260

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

示例:
给定 nums = [1, 2, 1, 3, 2, 5], 返回 [3, 5].

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

解析:这里需要解释下异或运算的含义,异或就是找两个数不相同的位,我们很容易通过一次循环找到两个数的异或结果c,有了c怎么找到这两个数呢,首先找到他们第一个不相同的位,即通过firstBit = rst_xor & ~(rst_xor - 1)找到最低的不相同位,然后让所有在这一位上取值为1的数异或,那么就获得其中一个数a,有了a和c,那么b就很容易获得了
c = a^b
a = c^b
b = c^a

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        rst_xor = nums[0]
        rst = [0,0]
        for i in range(1,len(nums)):
            rst_xor = rst_xor ^ nums[i]
        firstBit = rst_xor & ~(rst_xor - 1)  

        for i in range(len(nums)):
            if(nums[i] & firstBit):
                rst[0] = rst[0] ^ nums[i];
        rst[1] = rst_xor ^ rst[0]
        return rst 

增加题目

一个整型数组里除了三个数字之外,其他的数字都出现了两次。请找出这三个只出现一次的数字?

解析:假设这三个数是a b c,那么通过异或运算可以得到三个数的异或值,即d=a^b^c,所以题目等价于:假设一个数组中有3个不同的数字 a、b 和 c,已知 aXORbXORc = a ^ b ^ c ,求 a、b 和 c 。
根据异或特性可以得知:
(aXORbXORc ^ a) ^ (aXORbXORc ^ b) ^ (aXORbXORc ^ c) = 0
若令X=aXORbXORc ^ a Y=aXORbXORc ^ b Z=aXORbXORc ^ c,
X^Y^Z=0,那么X Y Z 三个数中找到低位中第一个不为0的位置,在这个位置上X Y Z有三种可能:111、010、101(000不用考虑,因为找的就是不为0的位置),而X^Y^Z=0,所以只可能是101,也就是两个相同一个不同,那么可以通过异或获得那个不同的数,也就是如果我们获取到这三个数的低位第一个为1的位置后,进行异或,并令低位第一位为1的位置为firstBit ,就可以找到三个中不同的那个,即遍历这三个数X Y Z,如果发现某个数异或 aXORbXORc 等于 firstBit ,这个数就是不为0的最低位不同的那个数,令这个数为a,找到它之后b^c=aXORbXORc ^ a,再根据上一题的方法就能找到b c

class Solution(object):
    def getFirstBit(self,num):
        return num & ~(num-1)

    def singleThreeNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        abc = nums[0]
        bc = 0
        rst = [0,0,0]
        firstBit = 0
        for i in range(1,len(nums)):
            abc = abc ^ nums[i]

        for i in range(len(nums)):
            firstBit = firstBit ^ Solution().getFirstBit(abc ^ nums[i])
        firstBit = Solution().getFirstBit(firstBit)

        for i in range(len(nums)):
            if(Solution().getFirstBit(abc ^ nums[i]) == firstBit):
                rst[0] = rst[0] ^ nums[i]

        bc = abc ^ rst[0]
        secondBit = bc & ~(bc - 1)  

        for i in range(len(nums)):
            if(nums[i] & secondBit):
                rst[1] = rst[1] ^ nums[i];
        rst[2] = bc ^ rst[1]        
        return rst 

参考:
https://blog.csdn.net/su20145104009/article/details/51295067

猜你喜欢

转载自blog.csdn.net/weixin_41043240/article/details/80000721