剑指offer第二版(Python3)--面试题56 :数组中数字出现的次数

第2章 面试需要的基础知识

第3章 高质量的代码

第4章 解决面试题的思路

第5章 优化时间和空间效率

  面试题39 : 数组中出现次数超过一半的数字

  面试题40 : 最小的k个数

  面试题42 : 连续子数组的最大和

  面试题43 : 从1到n整数中1出现的次数

  面试题45 : 把数组排成最小的数

  面试题49 : 丑数

  面试题50 : 第一个只出现一次的字符

  面试题51 : 数组中的逆序对

  面试题52 : 两个链表的第一个公共结点

  面试题53 : 在排序数组中查找数字

  面试题55 : 二叉树的深度、平衡二叉树

  面试题56 :数组中数字出现的次数

第6章 面试中的各项能力

第7章 两个面试案例


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

解题分析
  首先想到的是一道相似题型:一个整型数组里除了一个数字之外,其他的数字都出现了两次。这道题使用异或运算遍历一遍数组即可,但是本题有两个不同数,简单遍历一遍做异或运算显然不行。
  假如我们能把这两个不同的数分开到两个数组中,也就是把原数组分成两个数组,每个数组包含一个只出现一次的数,那么就可以用异或运算求解了。
  难点在于如何把这两个数分开放入到不同数组中。
  我们还是从头到尾依次异或数组中每个数,得到的异或结果就是那两个次数为1的异或结果,那么异或结果的二进制表示中至少有一位为1。找到这个异或结果中从右起第一位为1的位置,假设位置为index,然后对数组中所有数判断他们二进制形式下index位上是否为1,为1的分为一组,不为1的分为一组,这样数组就分为两组,并且那两个次数为1的数被分到不同组中了。然后分别对两组数组异或,返回结果即可。

 举例:[2, 4, 3, 6, 3, 2, 5, 5]

  1. 对数组每个数异或结果为得到0010;
  2. 根据数字的右起第二位是否为1,将数组分为[2, 3, 6, 3, 2],[4, 5, 5];
  3. 分别对上述两个数组异或,得到6和4。

实战

class Solution:
    # 返回[a,b] 其中ab是出现一次的两个数字
    def FindNumsAppearOnce(self, array):
        # write code here
        if not array or len(array) % 2:
            return None
        
        # 找到两个不同数异或结果中最右边的1
        number = 0
        digit = 1
        for num in array:
            number ^= num
        while number:
            if not number % 2:
                number = number >> 1
                digit = digit << 1
            else:
                break
        
        # 划分数组,同时计算异或
        a, b = 0, 0
        for num in array:
            if num & digit:
                a ^= num
            else:
                b ^= num
        
        return [a, b]

你可能感兴趣的:(算法设计)