剑指offer面试题40-数组中只出现一次的数字
2015-08-31 13:51
465 查看
题目:
一个整形数组里除了两个数字意外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.
要求时间复杂度是On,空间复杂度为O1
这个是上一篇 2016阿里巴巴java笔试题 的增强版...
还是使用异或,异或到了最后得到结果是怎么样的呢?
其余的数字都互相异或变成了0,所以最后的结果就是这2个不相同的数字的异或结果.
就假定要找的两个数字为数字A和数字B
那么怎么分别得到这2个数字呢?
异或:1^1=0,1^0=1
就看最后异或的结果:他是一个二进制数,那么出现1的地方肯定就是A与B的二进制不相同的地方.
那么就异或的结果中,第一次出现1的时候就说明此时A与B中较大的那个当前位上为1,较小的那个为0.
根据这个,就把所有的数字分为2组:当前位为1的,当前位为0的.
那么原先的一组数据被分为了2组,A,B又分别位于不同的组,那只要分别异或就行了..
例子:
比如说1,1,2,2,3,4,5,5
最后异或的结果就是3^4=1110
根据倒数第4位上是否为1,将原先的数组分为2组:
1,1,2,2,3
4,5,5
这样分别异或,第一组得到3,第二组得到4,完成
代码:
一个整形数组里除了两个数字意外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.
要求时间复杂度是On,空间复杂度为O1
这个是上一篇 2016阿里巴巴java笔试题 的增强版...
还是使用异或,异或到了最后得到结果是怎么样的呢?
其余的数字都互相异或变成了0,所以最后的结果就是这2个不相同的数字的异或结果.
就假定要找的两个数字为数字A和数字B
那么怎么分别得到这2个数字呢?
异或:1^1=0,1^0=1
就看最后异或的结果:他是一个二进制数,那么出现1的地方肯定就是A与B的二进制不相同的地方.
那么就异或的结果中,第一次出现1的时候就说明此时A与B中较大的那个当前位上为1,较小的那个为0.
根据这个,就把所有的数字分为2组:当前位为1的,当前位为0的.
那么原先的一组数据被分为了2组,A,B又分别位于不同的组,那只要分别异或就行了..
例子:
比如说1,1,2,2,3,4,5,5
最后异或的结果就是3^4=1110
根据倒数第4位上是否为1,将原先的数组分为2组:
1,1,2,2,3
4,5,5
这样分别异或,第一组得到3,第二组得到4,完成
代码:
public int[] find(int[] array) { // 异或所有,得到总异或的结果 int result = array[0]; for (int i = 1; i < array.length; i++) { result ^= array[i]; } // 求出倒数第几位为第一个1 // 这里count记录的是倒数第几-1 int count = -1; while (result != 0) { result = result >>> 1; count++; } // 分为两种情况来异或 int target1 = 0; int target2 = 0; for (int i = 0; i < array.length; i++) { if (((array[i] >>> count) & 1) == 1) { target1 ^= array[i]; } else { target2 ^= array[i]; } } return new int[] { target1, target2 }; }
相关文章推荐
- 2015年机器学习/数据挖掘面试总结
- 黑马程序员——Java的基本操作
- 老码农教你学英语
- 一个大公司程序员的牢骚
- 每日5道面试题八(java线程二)
- 黑马程序员——Java之多线程
- 最老程序员创业开发实训4---IOS平台下MVC架构
- 一道让人蛋疼的面试题
- 安卓常用开发命令
- 安卓的优缺点
- 面试题17:合并两个排序的链表
- [转]关于面试、简历之类的某人聊天的观点
- 面试题16:翻转链表
- 程序员能用一年的git技能整理
- 面试题15:链表中倒数第K个节点
- 大家在抢红包,程序员在研究红包算法
- 面试题14:调整数组顺序使奇数位于偶数前面
- 黑马程序员——36,Collections工具类,Arrays工具类,高级for循环,可变参数,静态导入
- 面试题13:在O(1)时间删除链表节点
- 剑指offer——面试题35:第一个只出现一次的字符(哈希)