leetcode 260

这题是个好题目,解法非常秀。首先O(n)时间复杂度,O(n)空间复杂度的算法非常容易得到。通过一个目录的数据结构来记录每个数字的出现次数,找出出现一次的数字,即解决。

非常cool的是O(n)时间复杂度,O(1)空间复杂度算法。我们通过之前的题目知道如果只有一个数字是不一样的话,那么我们可以通过异或的方式来找到这个数字,因为相同的数字经过异或操作就会变为0。那么我们这里可以也执行一遍异或操作。注意:这里得到的结果是两个单独数字的异或。因为这两个数字不同,所以它们异或的结果肯定至少有一位是1。如果这位是1,说明这两个数字的二进制在这一位置上是不同的,一个为1,一个为0。那么我们就可以根据这一位二进制对所有的数字进行分类。一类是二进制在这一位置为1的,一类是二进制在这一位置为0。因为相同的数字肯定会被分到同一类,所以现在这两类每一类都有且只有一个单独的数字。这时候我们再对这两类进行异或操作,就能够得到我们想要的两个数字(想到这个方法的一定是个天才。。。)此题是好题,mark

空间复杂度O(n)(运行时间居然beat 100% emmmmm):

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        result = []
        dir = {}
        for i in range(len(nums)):
            value = nums[i]
            if value not in dir.keys():
                dir[value] = 1
            else:
                dir[value] = 2
        for i,j in dir.items():
            if j == 1:
                result.append(i)
        return result

sign = temp & ~(temp-1) 这一步可以得到temp最右边为1的那一位,然后其他位都是0。

有两种情况,一种是temp的二进制最后一位为1,那么减去后除了最后一位为0,其他不变,然后取反,最后一位为1,其他位全变,最后一并,只剩下最后一位保持为1.

第二种假设我们看 最右边出现10的这个位置,当我们减去1之后,变成01,在10后面的所有0都变成了1,在10前面的数字不会改变,然后再取反,10前面的数字全部改变,10后面数字全部变成0.最后并的时候,因为10后面的都是0,所有结果为0.前面因为相当于取反后再并,所以也为0,最后就剩下了10中的那个1.

空间复杂度O(1):

class Solution:
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        temp = 0
        result = []
        for num in nums:
            temp ^= num
        sign = temp & ~(temp-1)
        n1 = 0
        n2 = 0
        for num in nums:
            if num & sign > 0:
                n1 ^= num
            else:
                n2 ^= num
        result.append(n1)
        result.append(n2)
        return result

猜你喜欢

转载自blog.csdn.net/bengepai/article/details/82501874
今日推荐