137. 只出现一次的数字 II -详解

题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,3,2]
输出: 3
示例 2:

输入: [0,1,0,1,0,1,99]
输出: 99

解法1

与Leetcode 136 不同的是,136是 2n+1, 可以直接异或,而这题是3n+1 .既然是3n+1 的思路,用 set 去重之后,*3 减去 不去重直接sum 就是重复之数的两倍 ,对应解法一,O(n) ,但是set 用到了额外空间,所以这并不是 最符合题目要求 的解法。

 def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        r = (3* sum(set(nums)) - sum(nums)) // 2
        return r

解法2

如上所说,3n+12n+1 的区别在于 a ^ a 可以直接抵消,而 a ^ a ^a不能直接抵消,如果找到 3数抵消 的运算方式就可以解决问题。
137. 只出现一次的数字 II -详解_第1张图片

  • 核心思路:可以看到 在 a,b = 0的基础上,遍历nums ,得到 i 。通过 a = (a^i) ; b= (b^i)的操作 可以将 i 赋值给 a,b,所以推出右边的运算表达式,
    此时问题来了:当a =i时,b应该等于0 才对啊,所以 b= (b^i) 需要作出调整, b= (b^i) = i ,而 i & ~i =0 ,此时 a=i,所以 i & ~a=0 ,所以 运算表达式变为
   a =  (a ^ i)  & ~b
   b =  (b ^ i)  & ~a

拿测试用例:[2,2,3,2] 推演,过程如下,最终返回a值,即为重复值。
时间复杂度为O(n) 。

137. 只出现一次的数字 II -详解_第2张图片

def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
		a, b = 0, 0
        for num in nums:
            a =  (a ^ num)  & ~b
            b =  (b ^ num)  & ~a
        return a

你可能感兴趣的:(LeetCode,代码规范)