题目描述:

一个数组里,除了三个数是唯一出现的,其余的数都出现了偶数次,找出这三个数中任意一个。比如数组序列为[1,2,4,5,6,4,2],只有1、5、6这三个数字是唯一出现的,数字2、4均出现了偶数次,只需要输出数字1、5、6中的任意一个就行。

分析:

题目得出的信息:

(1)数组中的元素一定为奇数个;

(2)由于只有三个数字均出现过一次,显然这三个数字不相同,因此,这三个数字对应的二进制也不可能完全相同。

解题思路:

因此可知:必定能找到二进制数中的某一个bit来区分这三个数(这一个bit的取值或者为0,或者为1),当通过这一个bit的值对数组进行分组的时候,这三个数一定是可以被分到两个子数组中去,。此时我们只需要重点关注哪个子数组中分配了这三个数的其中一个,就可以很容易得到这个数字了。当数组被划分成两个子数组时,这一个bit的值为1的数被分到一个子数组subArray1中,这一个bit的值为0的数被分到了另外一个子数组subArray0.

(1)如果subArray1中元素个数为奇数个,那么对subArray1中的所有数字进行异或操作;由于a^a=0,a^0=a,出现两次的数字通过异或操作得到结果为0,然后再与只出现一次的数字执行异或操作,得到的结果只出现一次的数字。

(2)如果subArray0中元素个数为奇数个,那么对subArray0中的所有数字进行异或操作得到的结果就是其中一个只出现一次的数字。

区分三个数字bit位及算法的实现思路:

32位平台为例,一个int类型的数字占用32位空间,从右往左使用每一位对数组进行分组,分组过程中,计算这个bit值为0的数字的异或的结果result0,出现次数count0;这个bit值为1的所有数字异或结果result1,出现次数为count1;

如果count0是奇数且result1 != 0 ,那么说明这三个数的其中一个数被分配到了这一个bit为0的子数组,因此,这个子数组中所有数字异或的值result0一定为出现的数字。(如果result1=0说明这一个bit不能用来区分这三个数字,此时这三个数字都被划分到子数组subArray0中,因此,result1!=0就可以确定这一个bit可以被用来划分这三个数字)

同理,如果count1是奇数且result0!=0,那么result1就是其中一个出现1次的数。

以[6,3,4,5,9,4,3]为例,出现1次的数字为6(110)、5(101)、9(1001),从右往左第一位就可以区分这三个数字,用这个bit位可以把数字区分为两个子数组subArray0=(6,4,4)和subArray1=(3,5,9,3)。subArray1中所有元素异或的值不等于0,说明出现一次的数字一定在subArray1中出现了,而subArray0中的元素个数为奇数个,说明出现一次的数字其中只有一个被分配到subArray0中了,所以subArray0中所有的元素异或的结果就是这个出现1次的数字6,实现算法的python代码如下:

#判断数字n的二进制数从右往左的第i位是否为1
def isOne(n,i):
return (n&(1<<i)) == 1 def findSingle(arr):
size = len(arr)
for i in range(32):
result0 = result1 = count0 = count1 = 0
for j in range(size):
if isOne(arr[j],i):
result1 ^= arr[i]
count1 += 1
else:
result0 ^= arr[j]
count0 += 1
"""
bit值为1的子数组元素个数为奇数时,且出现1次的的数字被分配到bit值为0的子数组,
说明只有一个出现的数字被分配到bit的值为1的子数组中,异或记过就是这个出现一次的数字
"""
if count1 % 2 == 1 and result0 != 0:
return result1
#只有一个出现一次的数字被分配到bit值为0的子数组中
if count0 % 2 == 1 and result1 != 0:
return result0
return -1

算法面试题(python)——如何找出数组中出现一次的数的更多相关文章

  1. 找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数

    找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数 #include<iostream>using namespace s ...

  2. #7 找出数组中第k小的数

    「HW面试题」 [题目] 给定一个整数数组,如何快速地求出该数组中第k小的数.假如数组为[4,0,1,0,2,3],那么第三小的元素是1 [题目分析] 这道题涉及整数列表排序问题,直接使用sort方法 ...

  3. 一起来刷《剑指Offer》-- 题目一:找出数组中重复的数字(Python多种方法实现)

    数组中重复的数字 最近在复习算法和数据结构(基于Python实现),然后看了Python的各种"序列"--比如列表List.元组Tuple和字符串String,后期会写一篇博客介绍 ...

  4. python找出数组中第二大的数

    #!usr/bin/env python #encoding:utf-8 ''''' __Author__:沂水寒城 功能:找出数组中第2大的数字 ''' def find_Second_large_ ...

  5. 找出数组中出现奇数次的元素<异或的应用>

    点击打开链接:百度面试题之找出数组中之出现一次的两个数(异或的巧妙应用) 题目描述|:给定一个包含n个整数的数组a,其中只有一个整数出现奇数次,其他整数都出现偶数次,请找出这个整数 使用异或操作,因为 ...

  6. 《剑指offer》第三_一题(找出数组中重复的数字,可改变数组)

    // 面试题3(一):找出数组中重复的数字 // 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内.数组中某些数字是重复的,但不知道有几个数字重复了, // 也不知道每个数字重复了几次.请 ...

  7. [LeetCode] Find All Numbers Disappeared in an Array 找出数组中所有消失的数字

    Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...

  8. 剑指Offer:找出数组中出现次数超过一半的元素

    题目:找出数组中出现次数超过一半的元素 解法:每次删除数组中两个不同的元素,删除后,要查找的那个元素的个数仍然超过删除后的元素总数的一半 #include <stdio.h> int ha ...

  9. 找出数组中最大值and索引

    找出数组中的最大值和和最大值的索引位置..... 第一中方法: /** * 找出数组中最大值和最大值的索引 * @param args */ public static void main(Strin ...

随机推荐

  1. 【Django-URL name详解005】

    1.打开zqxt_views/urls.py from django.contrib import admin from django.urls import path from calc impor ...

  2. linux下的缓存机制及清理buffer/cache/swap的方法梳理 (转)

    一.缓存机制介绍 在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果 ...

  3. Python day 03

    dya 03 今日内容 整形 布尔类型 字符串 补充 运算符补充 in value = '我是中国人' # 判断'中国'是否是value所代指的字符串的子序列. v1 = '中国' in value ...

  4. HDU 4417 Super Mario(主席树 区间不超过k的个数)题解

    题意:问区间内不超过k的个数 思路:显然主席树,把所有的值离散化一下,然后主席树求一下小于等于k有几个就行.注意,他给你的k不一定包含在数组里,所以问题中的询问一起离散化. 代码: #include& ...

  5. Jenkins学习

    1.jenkins启动卡在密码初始化处不动的情况,参照: https://blog.csdn.net/lylload/article/details/82754101 https://blog.csd ...

  6. html2canvas文字重叠(手机端)

    发现情况: 1.设置文字居中,文字自动换行后文字有重叠   text-align: center; 解决办法: text-align: left; text-align: justify;等 2.使用 ...

  7. Ubuntu14.04+Dell 7060安装无线/有线网络驱动

    7060的有线网卡I219-LM,可以用e1000e的驱动 1.sudo mkdir -p /usr/local/src/e1000e (在/usr/local/src/中新建文件夹e1000e) s ...

  8. POJ 1321 棋盘问题(搜索的方式)

    Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子 ...

  9. Android之人脸识别

    **前言** 人工智能时代快速来临,其中人脸识别是当前比较热门的技术,在国内也越来越多的运用,例如刷脸打卡.刷脸App,身份识别,人脸门禁等等.当前的人脸识别技术分为WEBAPI和SDK调用两种法方式 ...

  10. C#通过DocX创建word

    网上有一些基础的东西,但是比如插入图片,就没有找到方案,最终自己摸索出来的. 1.首先通过Nuget获取引用,关键字:“DocX” 2.示例代码 class Program { static void ...