[剑指Offer] 56_数组中数字出现的次数

题目1:数组中只出现一次的两个数字

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

例:

输入:[2, 4, 3, 6, 3, 2, 5, 5]
输出:4, 6


思路

  1. 利用异或运算的特点,a^a = 0;0^a = a。第一次遍历异或的结果为s = n1 ^ n2。此时s的二级制位表征了n1和n2各位上的异同。只要将n1和n2分在两个子数组中,并再次异或遍历,即可得到各自的值。因此用s中为1的位来划分子数组即可。
    1. 时间复杂度:O(n)
    2. 空间复杂度:O(1)

代码

思路1:时间复杂度:O(n),空间复杂度:O(1)

def numbers_appear_once(nums):
    """    
    :param nums:array 
    :return: (num1, num2)
    """
    if not nums:
        return None
    s = n1 = n2 = 0
    for num in nums:
        s ^= num
    bit = 0
    while s & 1 == 0:
        s = s >> 1
        bit += 1
    div = 1 << bit
    for num in nums:
        if num & div:
            n1 ^= num
        else:
            n2 ^= num
    return n1, n2

题目2:数组中唯一只出现一次的数字

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


思路

  1. 遍历数组不进位相加后得到, s = n 0 + n 1 + . . . + n i = &lt; b 0 , b 1 , b 2 , . . . , b i &gt; s =n_0+n_1+...+n_i = &lt;b_0, b_1, b_2,..., b_i&gt; s=n0+n1+...+ni=<b0,b1,b2,...,bi> b i = 3 ∗ ( n 0 + . . . + n n u m − 1 + n n u m + 1 + . . + n i ) + n n u m b_i=3*(n_0+...+n_{num-1}+n_{num+1}+..+n_i) +n_{num} bi=3(n0+...+nnum1+nnum+1+..+ni)+nnum,只要将每二进制位上的和对3求余即可。
    1. 时间复杂度:O(n)
    2. 空间复杂度:O(1)
  2. 本题仍然能够用异或来解。要求是构造一个运算@,运算三次归零。0@S@S@S=0。 b = ~a & (b ^ num);a = ~b & (a ^ num)。分析运算的过程,该运算本质是用【ab】=00->01->10->00表示出现的次数。当该数字只有一次时,b相当于完成一次异或,b=num,a=0;运算第二次,b=num^num = 0,a = num;运算第三次,b=0,a=0。用2个比特位来记录。
    1. 时间复杂度:O(n) 快于思路1。
    2. 空间复杂度:O(1)

代码

思路1:时间复杂度:O(n),空间复杂度:O(1)

def number_appearing_once(nums):
    cache = [0] * 32
    for num in nums:
        bit_mask = 1
        for i in range(31,-1,-1):
            if num & bit_mask:
                cache[i] += 1
            bit_mask  = bit_mask << 1
    ans = 0
    for i in range(32):
        ans = ans << 1
        ans += cache[i] % 3
    return ans if ans < 2 ** 31 else ans - 2 ** 32

思路2:时间复杂度:O(n),空间复杂度:O(1)

def number_appearing_once_2(nums):
    a, b = 0, 0
    for num in nums:
        b = ~a & (b ^ num)
        a = ~b & (a ^ num)
    return b

思考

相同的题目

LeetCode 137. 只出现一次的数字 II

题目

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

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

示例 1:

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

示例 2:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值