九度OJ-题目1351:数组中只出现一次的数字
来源:互联网 发布:qq飞车鬼战刀数据 编辑:程序博客网 时间:2024/05/22 04:59
题目链接地址:
九度OJ-题目1351:数组中只出现一次的数字
题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
输入:
每个测试案例包括两行:
第一行包含一个整数n,表示数组大小。2<=n <= 10^6。
第二行包含n个整数,表示数组元素,元素均为int。
输出:
对应每个测试案例,输出数组中只出现一次的两个数。输出的数字从小到大的顺序。
样例输入:
8
2 4 3 6 3 2 5 5
样例输出:
4 6
解题思路:
之前做过“数组中只有一个数字出现一次,而其他的数字都出现过两次”这个题目,那道题用的是异或运算。原理如下:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
a ^ a = 0
也就是说两个相同元素异或得到的结果是0。
但是这道题升级了,变成了“数组中有两个数字出现一次,而其他的数字都出现过两次”,这下我没辙了。。。
于是请教范神,毕竟是玩数学的大神,立马就给了我一个思路:虽然出现一次的数字变成了两个,但是其他的数字都出现过两次,所以还是要用到异或运算。现在关键的问题是如何把这两个只出现一次的数字分开。
举个栗子,对于测试用例2 4 3 6 3 2 5 5 进行异或运算可以得到
2 ^ 4 ^ 3 ^ 6 ^ 3 ^ 2 ^ 5 ^ 5 = 4 ^ 6 = 2,
接下来就是要根据异或结果2分解出4和6,
将4,6,2换成二进制,具体如下:
4 ---- > 1 0 0
6 ---- > 1 1 0
2 ---- > 0 1 0
从右至左遍历数字’2’的二进制,可以得知第2个二进制位是1,
而异或运算满足:1 ^ 1 = 0,0 ^ 0 = 0,0 ^ 1 = 1,1 ^ 0 = 1;
所以可以得知数字4和6的第2个二进制位第一次出现了不同,其中4的第2个二进制位是0,6的第2个二进制位是1。
通过这个特点,我们就可以将数组中的数字分为两类:
①从左至右遍历整数所对应的二进制数,数字的第2个二进制位是0;
②从左至右遍历整数所对应的二进制数,数字的第2个二进制位是1;
属于第①类的数字与4进行异或,属于第②类的数字与6进行异或。
因此可以原来的数组就分为以下两组:
{4,5,5} 和{2,2,3,3,6},对这两组数字分为进行异或运算就可以得到数组中只出现一次的数字4和6。
AC代码如下:
#include<stdio.h>#define MAX 1000001int number[MAX]; /*** 输入含有n个元素的整形数组* @param n 表示数组的元素个数* @return void*/void inputNumberArray(int n){ int i; for(i = 0;i < n;i++) scanf("%d",&number[i]);} /*** 找到两个数字对应二进制中的最低不同位* @param exclusiveOr 数组中所有元素异或得到的结果,因为除了两个元素之外,* 其余元素都出现了两次,所以这个异或结果等价于两个只* 出现一次的数字异或所得的结果* @return int 两个只出现一次的数字的二进制最低不同位所对应的十进制数*/int getDifferentBit(int exclusiveOr){ int differentBit = 1; while(0 == (exclusiveOr & 1)) { differentBit = differentBit << 1; exclusiveOr = exclusiveOr >> 1; } return differentBit;} /*** 找到数组中两个只出现一次的数字* @param n 表示数组的元素个数* @return void*/void findTwoNumberOnlyOnce(int n){ int exclusiveOr = 0; // 保存异或运算所得到的结果 int differenceBit; int i; int a = 0,b = 0; int temp; for(i = 0;i < n;i++) { exclusiveOr = exclusiveOr ^ number[i]; } differenceBit = getDifferentBit(exclusiveOr); // 根据number[i]的第log2differenceBit位的数字是否为1,可以将数组中的元素分为两类: // 一类数字的二进制与a的第log2differenceBit位相同,这类数字与a进行异或; // 另一类的数字的二进制则与b的第log2differenceBit位相同,这类数字与b进行异或。 // 而与a同类的数字都各自出现了两次,这些数字两两异或后结果为0,最后的异或结果中只剩下a,同理可以得到b。 for(i = 0;i < n;i++) { if(0 != (number[i] & differenceBit)) { a = a ^ number[i]; } else { b = b ^ number[i]; } } // 如果a > b,则将a与b进行交换,保证最后的结果是a < b。 if(a > b) { temp = a; a = b; b = temp; } printf("%d %d\n",a,b);} int main(){ int n; while(EOF != scanf("%d",&n)) { inputNumberArray(n); findTwoNumberOnlyOnce(n); } return 0;} /************************************************************** Problem: 1351 User: blueshell Language: C++ Result: Accepted Time:780 ms Memory:4928 kb****************************************************************/
- [九度oj]题目1351:数组中只出现一次的数字
- 九度OJ-题目1351:数组中只出现一次的数字
- 九度oj 数组中只出现一次的数字
- 九度OJ—题目1351:数组中只出现一次的数字(vector与数组的区别)
- 九度OJ 1351 数组中只出现一次的数字
- 九度OJ 1351 数组中只出现一次的数字 (位操作)
- 九度OJ 1351:数组中只出现一次的数字 (位运算)
- 题目1351:数组中只出现一次的数字-九度
- 九度 题目1351:数组中只出现一次的数字
- 九度 题目1351:数组中只出现一次的数字
- 【剑指offer】【九度oj】数组中只出现一次的数字
- 整形数组中只出现一次的数字(剑指Offer,九度OJ)
- 题目1351:数组中只出现一次的数字
- **题目1351:数组中只出现一次的数字
- 九度笔记之 1351:数组中只出现一次的数字
- 题目40:数组中只出现一次的数字
- 题目1351:数组中只出现一次的数字 (2014.2.16)
- 数组中只出现一次的数字
- HDU--2056
- opensips 调试过程中的错误总结和对应解决方案
- Android Touch事件传递机制解析
- 使用 JavaScript 控制 HTML5 视频播放器
- prezi 中实现淡入动画
- 九度OJ-题目1351:数组中只出现一次的数字
- ubuntu14.10下安装MATLAB-2013b
- 常用meta整理
- 新GRE考试阅读和老GRE阅读有哪些不同?
- 继承的概念:继承是指类与类之间的继承关系 ,子类继承父类,子类可以将父类的属性方法继承下来 网址:www.iphonetrain.com 以下代码是了车类与出租车类 共同继承了Car属性
- LeetCode 之 Valid Parentheses — C++ 实现
- 深度学习入门资料
- 内联块状元素
- 面向对象之继承