剑指 Offer 56 - I 至 56 - II 数组中数字出现的次数 I && II 题解

Posted 风去幽墨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 56 - I 至 56 - II 数组中数字出现的次数 I && II 题解相关的知识,希望对你有一定的参考价值。

剑指 Offer 56 - I. 数组中数字出现的次数

题意:

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

题解:

面试常考题。
最原始版本(最简单版本):

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

根据异或的原理 a^b^a = b,a^a = 0。很容易得到整体异或后最终结果即为答案。
升级版本 1.0 就是这道题。
区别于简单版本是有两个数字(记为a,b)出现了偶数次。
这里依然可以顺着异或的方向去思考,整体异或的结果是a^b。很明显a和b是不同的,所以a^b的结果必然不是0,那么肯定在二进制下有某一位为1,只有0^1=1^0 =1,所以可以得到a和b在这一位上有一个为0一个为1。依据这个可以将所有元素分为两组,一组在该位上为1,一组为0.然后将两组元素各自异或后得到的结果就是a和b。

代码:

class Solution:
    def singleNumbers(self, nums: List[int]) -> List[int]:
        sum = nums[0]
        for i in nums[1:]:
            sum^=i
        for i in range(0,32):
            if sum&(1<<i):
                a,b=None,None
                for j in nums:
                    if j&(1<<i):
                        a = a^j if a else j
                    else:
                        b = b^j if b else j
                break
        return [a,b]

剑指 Offer 56 - II. 数组中数字出现的次数 II

题意:

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

题解:

解法1:位运算(暴力解法)
利用位运算计算二进制下每一位为1的次数,若次数是3的倍数,则表明ans在该位上为0反之为1。
解法2:位运算优化
思路与解法1类似,但更为巧妙。
原解析写的更清楚,详见具体解析:

代码:

#法一
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        cnt = [0]*32
        for i in nums:
            for j in range(0,32):
                if i&(1<<j):
                    cnt[j]+=1
        ans = 0
        for i in range(0,32):
            if cnt[i]%3!=0:
                ans += 1<<i
        return ans 
#法二
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        ones, twos = 0, 0
        for num in nums:
            ones = ones ^ num & ~twos
            twos = twos ^ num & ~ones
        return ones

以上是关于剑指 Offer 56 - I 至 56 - II 数组中数字出现的次数 I && II 题解的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer 56 - II. 数组中数字出现的次数 II

剑指 Offer 56 - II. 数组中数字出现的次数 II

剑指offer位运算56 - II. 数组中数字出现的次数 II

LeetCode(剑指 Offer)- 56 - II. 数组中数字出现的次数 II

LeetCode(剑指 Offer)- 56 - II. 数组中数字出现的次数 II

算法leetcode剑指 Offer 56 - II. 数组中数字出现的次数 II(多语言实现)