转载请注明出处:http://blog.csdn.net/mmc_maodun/article/details/27800577

题目:一个int数组中有三个数字a、b、c仅仅出现一次,其它数字都出现了两次。

请找出三个仅仅出现一次的数字。

上篇博文中我们求的是两个仅仅出现一次的数字。且时间复杂度为O(n),这次是三个,能够相同考虑将数组先分成两个子数组,求出当中一个仅仅出现一次的数字,而后再将还有一个子数组分成两个子数组。再分别求这两个仅仅出现一次的数字。何海涛的博客给的就是这样的思路,并给出了具体的证明过程,详见:http://zhedahht.blog.163.com/blog/static/25411174201283084246412/,但该方法真的要自己去想,非常难想到,并且假设是面试的话。非常难给面试官讲懂。以下介绍第二种方法。该方法具一定的通用性,对于2个。3个出现一次的数字这类的问题,都能够依照该思路去求解,仅仅是时间复杂度可能要略微大些,为O(8*sizeof(int)*n),8*sizeof(int)事实上即使int的位,在一般的32位系统中,它为32,而n自然就是数组的长度了。

该方法的思路例如以下:

首先因为有3个数字出现一次,其它的都出现两次。所以n肯定为奇数,该方法通过扫描整数的每一位来逐个推断。

再看这3个仅仅出现一次的数字,他们的bit位肯定不可能全部相同。也就是说。尽管有些bit位上的数可能相等。但肯定至少存在某一个bit位,这三个数中,有两个数的该bit位为1,一个数的该bit位为0。或者两个数的该bit位为0。一个数的该bit位为1。

我们能够通过扫面int的全部bit位,扫描每一个bit位的时候。遍历数组,假设能找出符合上面条件的,我们就能够找出当中的一个仅仅出现一次的数字,该数字与另外两个仅仅出现一次的数的bit位不同。找到一个之后,就能够将其与数组的最后一个元素交换。再在前面n-1个数中找出另外两个就能够了。方法的话。能够直接用上篇博文中介绍的方法,也能够用该博文介绍的思路。

以下要来看下假设找出这个与另外两个数的该bit位不同的数。

先看第一种情况。假设a,b,c三个数中,有两个该bit位为0,还有一个为1,我们遍历数组,分别统计该数组元素中该bit位为1和0的元素个数。分别设为count1和count0,并同一时候将全部该bit位为1的元素异或,全部该bit位为0的元素异或。得到的结果分别设为temp1和temp0。假设count1为奇数。则可能有两种情况,a,b,c三个数的该bit位全为1。或者有两个为0,一个为1,假设有temp0==0,则说明是前一种情况(a,b。c的该bit位全为1的话,全部该bit位为0的每一个元素出现了两次。因此异或后的结果为0),此时没法找出当中的一个数。则直接跳到下次循环,继续推断下一个bit位,假设temp0。=0。则说明是后一种情况(说明该比bt位为0的元素异或后没有全然抵消,则说明有一个元素是仅仅出现一次的)。此时当中一个仅仅出现一次的数字就是temp0(反复的元素异或后都抵消了)。

第二种情况,是两个该bit位为1。还有一个为0的情况,分析思路与上面的相似。

非常明显,这样的扫描每一个bit位来进行推断的思路能够解决整个的这一类问题,自然也能够求出上篇博文中两个仅仅出现一次的数字。具体思路不再给出,基本的推断根据,一般都是bit位为1或0的数字的个数的奇偶。bit位为1的元素异或,bit位为0的元素异或后的结果是否为0的推断。

以下给出这道题目的完整代码:

#include<stdio.h>

/*
通过扫面每一位,先找出一个仅仅出现一次的数
*/
int FindOneNumAppearOnce(int *arr,int len)
{
int count1 = 0; //某一位上1的个数
int count0 = 0; //某一位上0的个数
int temp1 = 0; //某一位为1的全部数相异或的结果
int temp0 = 0; //某一位为0的全部数相异或的结果 int i,j;
for(i=0;i<8*sizeof(int);i++) //循环计算每一位的以上四个数据
{
count1 = count0 = temp1 = temp0 = 0;//每次计算下一位时清零
for(j=0;j<len;j++)
{
//每次向左移一位进行计算
if(arr[j] & (1<<i)) //该位为1时
{
temp1 ^= arr[j];
count1++;
}
else
{
temp0 ^= arr[j];
count0++;
}
} if(temp1 & 1) //某位上有奇数个1
{
if(temp0 == 0) //此时3个不同数的该位都为1
continue;
else //此时3个不同数的该位有1个1,2个0
return temp1;
}
else //某位上有偶数个1
{
if(temp1 == 0) //此时3个不同数的该位都为0
continue;
else //此时3个不同数的该位有1个0,2个1
return temp0;
}
}
} /*
返回num的最低位的1。其它各位都为0
*/
int FindFirstBit1(int num)
{
//二者与后得到的数,将num最右边的1保留下来,其它位的全部置为了0
return num & (-num);
} /*
推断data中特定的位是否为1。
这里的要推断的特定的位由res确定,
res中仅仅有一位为1。其它位均为0。由FindFirstBit1函数返回。
而data中要推断的位便是res中这唯一的1所在的位
*/
bool IsBit1(int data,int res)
{
return ((data&res)==0) ? false:true;
} void FindTwoNumsAppearOnce(int *arr,int len,int *num1,int *num2)
{ int i;
int AllXOR = 0;
//全部异或
for(i=0;i<len;i++)
AllXOR ^= arr[i]; int res = FindFirstBit1(AllXOR); *num1 = *num2 = 0;
for(i=0;i<len;i++)
{
if(IsBit1(arr[i],res))
*num1 ^= arr[i];
else
*num2 ^= arr[i];
}
} /*
交换两个int变量
*/
void Swap(int *a,int *b)
{
if(*a != *b)
{
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
} /*
找出这三个仅仅出现一次的数字
*/
void FindThreeNumsAppearOnce(int *arr,int len,int *num1,int *num2,int *num3)
{
if(arr==NULL || len<3)
return; *num1 = FindOneNumAppearOnce(arr,len); //找到第一个找出的数字,并与最后一个元素交换,便于接下来剩下的两个数字
int i;
for(i=0;i<len;i++)
if(*num1 == arr[i])
break;
Swap(&arr[i],&arr[len-1]); FindTwoNumsAppearOnce(arr,len-1,num2,num3);
} int main()
{
static int arr[1000000];
int n;
while(scanf("%d",&n) != EOF)
{
int i;
for(i=0;i<n;i++)
scanf("%d",arr+i); int num1,num2,num3;
FindThreeNumsAppearOnce(arr,n,&num1,&num2,&num3);
printf("%d %d %d\n",num1,num2,num3);
}
return 0;
}

測试结果:

版权声明:本文博客原创文章,博客,未经同意,不得转载。

【剑指offer】数字数组中只出现一次(2)的更多相关文章

  1. 《剑指offer》数组中只出现一次的数字

    本题来自<剑指offer> 数组中只出现一次的数字 题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路: 思路一:在<剑指of ...

  2. 【剑指Offer】数组中只出现一次的数字 解题报告(Python)

    [剑指Offer]数组中只出现一次的数字 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-intervie ...

  3. 【Java】 剑指offer(56-1) 数组中只出现一次的两个数字

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程 ...

  4. Go语言实现:【剑指offer】数组中只出现一次的数字

    该题目来源于牛客网<剑指offer>专题. 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 正常能想到哈希表来处理,但此题考查的是异或的知识, ...

  5. 剑指Offer 40. 数组中只出现一次的数字 (数组)

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了偶数次.请写程序找出这两个只出现一次的数字. 题目地址 https://www.nowcoder.com/practice/e02fdb54 ...

  6. 剑指offer:数组中只出现一次的数字

    题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路分析: 1. 直接想法,每个数字遍历,统计出现次数,复杂度O(n^2),超时. 2. 借助 ...

  7. 【剑指offer】数组中只出现一次的数

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 分析: 经典的异或技巧题 两个相同的数字异或的结果为0,一个数和0异或的结果是其本身,假设现在那 ...

  8. 【剑指offer】数组中只出现一次的数字

    题目:一个整型数组里除了两个数字之外,其他的数字都出现了偶数次.请写程序找出这两个只出现一次的数字. 思路1:使用HashMap存上所有的数字,数字作为Key,Value为对应的出现次数.这种做法可以 ...

  9. 《剑指offer》-数组中只出现一次的数字

    /* 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路: 如果是只有一个数字出现一次,那么所有数字做异或就得到结果: 现在有两个数字x,y分别出现一次 ...

  10. [剑指offer] 40. 数组中只出现一次的数字

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了偶数次.请写程序找出这两个只出现一次的数字. 思路: 解法一: 哈希表 class Solution { public: void Find ...

随机推荐

  1. 构建自己的Java并发模型框架

    Java的多线程特性为构建高性能的应用提供了极大的方便,可是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题须要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误. 另外.应用逻辑和线程逻辑 ...

  2. Ising模型(伊辛模型)

    Ising模型(伊辛模型)是一个最简单且能够提供非常丰富的物理内容的模型.可用于描写叙述非常多物理现象,如:合金中的有序-无序转变.液氦到超流态的转变.液体的冻结与蒸发.玻璃物质的性质.森林火灾.城市 ...

  3. 采用PopupWin控制消息推送功能

    最近的项目需要,急需实现消息推送功能.接连试了很多办法,让我们用JavaScript为了实现啊,其效果是不咋好,最后,我发现了一个PopupWin这个,看着眼前的成绩不错,开始使用. 1.准备工作.先 ...

  4. android 4.0 中出错 java.lang.UnsupportedOperationException

    在android4.0中  画图的时候使用: canvas.clipPath(path, Region.Op.XOR); 报错 java.lang.UnsupportedOperationExcept ...

  5. C++ 版本的split_string

    vector<string> split_string(const string &in, char del, bool skip_empty) { vector<strin ...

  6. Hadoop读书笔记(二)HDFS的shell操作

    Hadoop读书笔记(一)Hadoop介绍:http://blog.csdn.net/caicongyang/article/details/39898629 1.shell操作 1.1全部的HDFS ...

  7. Xamarin.Android 入门实例(4)之实现对 SQLLite 进行添加/修改/删除/查询操作

    1.Main.axml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns: ...

  8. Xamarin.Android 在VS下调试时提示 In mgmain JNI_OnLoad 程序“Mono”已退出 解决办法

    原因是使用了破解版的 Xamarin,调试时不能使用共享库

  9. MySQL与逻辑模块

    启动MySQL 1.初始化模块运行&&存储引擎初始化运行 2.1中运行完毕后 ---->连接管理模块接手 3.连接管理模块启动处理client连接请求的监听程序(tcp/ip 网 ...

  10. PHPthinking官方论坛

    PHPthinking官方论坛正式上线一个月!眼下.我们已经有数百个固定用户的.论坛发展迅速,所有份额一些技术贴,我们希望,其他许多用户增加来,创建学习.交流更方便.丰富的内容PHP座谈会! PHPt ...