关于位运算参考:http://blog.csdn.net/morewindows/article/details/7354571

关于位操作这里用到的三个要点:

1: 用位操作实现求一个数中的最后一个1

int lastbitof1(int number)

{

return number&~(number-1)//数字减去1之后取反,然后与原来的数字做位与运算就求出了数字最后一个1

}

2: 用位操作实现求一个数中的第一个1

int  firstbitof1(int number)

{

int indexbit=0;

while((num&1)==0&&(indexbit<8*sizeof(int)))

{

number=number>>1;

++indexbit

}

return indexbit;

}

3:    用位操作实现求一个数中有多少个1

把一个数减去1,再和原来的整数做与运算,会吧整数最右边的一个1变成0。那么一个整数中有多少个1,就会做多少次这样的运算。

int  numberof1(int number)

{

int count=0;

while(number)

{

++count;

number=(number-1)&number;

}

return count;

}

4   数组中只有一个整数出现了一次,其它整数都是出现了偶数次,求这个只出现了一次的整数

int FindNumAppearOnce(int * data,int length)

{

int number=0;

for(int i=0;i<length-1;i++)

number^=data[i];

return number;

}

题目:一个数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。

分析:在博客http://zhedahht.blog.163.com/blog/static/2541117420071128950682/中我们讨论了如何在一个数组中找出两个只出现一次的数字。在这道题中,如果我们能够找出一个只出现一次的数字,剩下两个只出现一次的数字就很容易找出来了。

如果我们把数组中所有数字都异或起来,那最终的结果(记为x)就是a、b、c三个数字的异或结果(x=a^b^c)。其他出现了两次的数字在异或运算中相互抵消了。

我们可以证明异或的结果x不可能是a、b、c三个互不相同的数字中的任何一个。我们用反证法证明。假设x等于a、b、c中的某一个。比如x等于a,也就是a=a^b^c。因此b^c等于0,即b等于c。这与a、b、c是三个互不相同的三个数相矛盾。

由于x与a、b、c都各不相同,因此x^a、x^b、x^c都不等于0。

我们定义一个函数f(n),它的结果是保留数字n的二进制表示中的最后一位1,而把其他所有位都变成0。比如十进制6表示成二进制是0110,因此f(6)的结果为2(二进制为0010)。f(x^a)、f(x^b)、f(x^c)的结果均不等于0。

接着我们考虑f(x^a)^f(x^b)^f(x^c)的结果。由于对于非0的n,f(n)的结果的二进制表示中只有一个数位是1,因此f(x^a)^f(x^b)^f(x^c)的结果肯定不为0。这是因为对于任意三个非零的数i、j、k,f(i)^f(j)的结果要么为0,要么结果的二进制结果中有两个1。不管是那种情况,f(i)^f(j)都不可能等于f(k),因为f(k)不等于0,并且结果的二进制中只有一位是1。

于是f(x^a)^f(x^b)^f(x^c)的结果的二进制中至少有一位是1。假设最后一位是1的位是第m位。那么x^a、x^b、x^c的结果中,有一个或者三个数字的第m位是1。

接下来我们证明x^a、x^b、x^c的三个结果最后一位是1的是第m位不可能都是1。还是用反证法证明。如果x^a、x^b、x^c的第m位都是1,那么a、b、c三个数字的第m位和x的第m位都相反,因此a、b、c三个数字的第m位相同。如果a、b、c三个数字的第m位都是0,x=a^b^c结果的第m位是0。由于x和a两个数字的第m位都是0,x^a结果的第m位应该是0。同理可以证明x^b、x^c第m位都是0。这与我们的假设矛盾。如果a、b、c三个数字的第m位都是1,x=a^b^c结果的第m位是1。由于x和a两个数字的第m位都是1,x^a结果的第m位应该是0。同理可以证明x^b、x^c第m位都是0。这还是与我们的假设矛盾。

因此x^a、x^b、x^c三个数字中,只有一个数字的第m位是1。于是我们找到了能够区分a、b、c三个数字的标准。这三个数字中,只有一个数字满足这个标准,而另外两个数字不满足。一旦这个满足标准数字找出来之后,另外两个数字也就可以找出来了。

这种思路的C++代码如下:

void getThreeUnique(vector<int>& numbers, vector<int>& unique)

{

if(numbers.size() < 3)

return;

int xorResult = 0;

vector<int>::iterator iter = numbers.begin();

for(; iter != numbers.end(); ++iter)

xorResult ^= *iter;

int flags = 0;

for(iter = numbers.begin(); iter != numbers.end(); ++iter)

flags ^= lastBitOf1(xorResult ^ *iter);//这里最终的运算结果是f(x^a)^f(x^b)^f(x^c),即三个不同的数与xorresult异或后在三个一同异或的其情况,

flags = lastBitOf1(flags);      //而根据上面的证明,假定最后一位是1的位是第m位,那么x^a、x^b、x^c中,位于m位上为1的只可能是有1个,所以根据这个第m位上是否为1                                                         // 可以找到第一个只出现一次的数,之后问题就转化为求数组中两个只出现一次的问题

// get the first unique number

int first = 0;

for(iter = numbers.begin(); iter != numbers.end(); ++iter)

{

if(lastBitOf1(*iter ^ xorResult) == flags)

first ^= *iter;

}

unique.push_back(first);

// move the first unique number to the end of array

for(iter = numbers.begin(); iter != numbers.end(); ++iter)

{

if(*iter == first)

{

swap(*iter, *(numbers.end() - 1));

break;

}

}

// get the second and third unique numbers  这个就是求数组中只有两个整数出现一次的,求这两个整数的算法

getTwoUnique(numbers.begin(), numbers.end() - 1, unique);

}

int lastBitOf1(int number)

{

return number & ~(number - 1);

}

void getTwoUnique(vector<int>::iterator begin, vector<int>::iterator end, vector<int>& unique)

{

int xorResult = 0;

for(vector<int>::iterator iter = begin; iter != end; ++iter)

xorResult ^= *iter;

int diff = lastBitOf1(xorResult);

int first = 0;

int second = 0;

for(vector<int>::iterator iter = begin; iter != end; ++iter)

{

if(diff & *iter)

first ^= *iter;

else

second ^= *iter;

}

unique.push_back(first);

unique.push_back(second);

}

数组中只出现一次的(一个数、两个数、三个数)相关推荐

  1. 数组中只出现一次的数字

    一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 数字都出现两次,则异或肯定为0. 考虑下这个题目的简化版--数组中除一个数字只出现1次外,其它数字都成对出 ...

  2. 【剑指offer-Java版】40数组中只出现一次的数字

    数组中只出现一次的数字:输入一个数组,该数组中有两个数字只出现了一次,其他数字都出现了两次,求出这两个只出现了一次的数字 要求时间复杂度为O(n)空间复杂度为O(1) 考虑一个数组中只有一个数字仅仅出 ...

  3. 《剑指offer》-- 第一个只出现一次的字符、数组中只出现一次的数字、字符流中第一个不重复的字符、数组中重复的数字

    一.第一个只出现一次的字符: 1.题目: 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写 ...

  4. 数组中只出现1次的2个数

    数组中只出现1次的2个数 如题所示: 思路 源代码如下: 如题所示: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字 可以先考虑如果只有1个数字出现1次,其 ...

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

    本文首发于我的个人博客:尾尾部落 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了偶数次.请写程序找出这两个只出现一次的数字. 解题思路 法一:大家都能想到的HashMap法 法二:异或法 ...

  6. 牛客题霸 [数组中只出现一次的数字] C++题解/答案

    牛客题霸 [数组中只出现一次的数字] C++题解/答案 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 题解: 用map来记录每个数字出现几次, ...

  7. 40:数组中只出现一次的数字

    /*** 面试题40:数组中只出现一次的数字* 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.*/ public class _40_num_one_ti ...

  8. 【难题+重点】剑指offer——面试题40:数组中只出现一次的数字

    剑指offer--面试题40:数组中只出现一次的数字 Solution1: 书中展示了很棒的思路: 关于异或的两个性质应该知道: (1) X^X = 0; (2) X^0 = X; class Sol ...

  9. 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

    给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个元素不能使用两遍. ...

  10. 找出数组中只出现了一次的数字(Java)

    找出数组中只出现了一次的数字 题目 题目分析 方法1 方法2 方法3 代码实现 主方法 方法1 第一种:使用计数器的 第二种:不使用计数器 方法2 方法3 总结 题目 给定一个非空整数数组,除了某个元 ...

最新文章

  1. AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML)
  2. 周鸿祎告诫员工:勿盲目把360看成巨头 不四处出击!
  3. # iOS 一窥并发编程底层(一)
  4. c语言中continue在case中,C語言switch case 語句中能否使用continue 關鍵字?
  5. Post 请求调试工具简介
  6. 鸟哥的Linux私房菜之Linux 的文件权限与目录管理(一)
  7. 企业网站优化用户体验以内容为主
  8. 微信公众号unionid问题
  9. 嵌入式使用Zbar解析二维码
  10. 微信开发学习二 -- 微信开发入门(简单demo)
  11. 硬件设计与实践:16位CPU设计
  12. Web Audio API之手把手教你用web api处理声音信号:可视化音乐demo
  13. NLP在线医生(一)
  14. sql server oracle转换,sql-server – 如何从SQL Server DBA转换到Oracle?
  15. 微信开发生成带参数的二维码的讲解
  16. 【shaderforge学习笔记】 Vector Operations(向量运算)
  17. PHP中的面向对象思想
  18. ubuntu20.04 server 无图形命令行安装
  19. iterm上安装oh-my-zsh连接失败
  20. 家里网络连不上outlook_outlook连不上公司网络

热门文章

  1. 2021春季学期-创新设计与实践-Lesson4
  2. 北京科技大学天津学院第三届智能车校内赛总决赛完美落幕
  3. APPLE:疑问驱动下的学习与实践
  4. NS4146 D类音频放大电路
  5. c语言课件 文件,C语言课件--文件.ppt
  6. 图书管理系统python代码课程设计报告_数据结构图书管理系统课程设计报告
  7. 四川音乐学录音艺术与计算机音乐,艺考中作曲专业和录音专业有什么不同呢?...
  8. nginx lua连接mysql_OpenResty的安装和在nginx中使用lua直接访问mysql达到数据接口的统一...
  9. url主机域名可以省略_网站迁移虚拟主机怎么样能不影响网站优化
  10. 讯飞语音识别_赛诺语音输入法报告 搜狗、讯飞、百度AI语音输入哪家强