【LeetCode】(260)Single Number III(Medium)
2015-08-24 23:35
295 查看
题目
Single Number III
Total Accepted: 3222 TotalSubmissions: 9193My Submissions
Question
Solution
Given an array of numbers
nums,
in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given
nums = [1, 2, 1, 3, 2, 5],
return
[3, 5].
Note:
The order of the result is not important. So in the above example,
[5, 3]is also correct.
Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
解析
找到一个不一样的数大家都知道用异或。找到两个方法差不多,中心思想是把这两个数划分到不同的两个类里面去。如何划分呢,将所有元素做一个异或,其实本质就是对这两个元素做了异或,异或的结果其实展现的就是这两个元素的不同。举个栗子
001, 010, 101, 101 ,111, 111, 110, 110
异或结果为011,说明那两个数最后一位是有区别的,根据这个就可以将所有的数进行划分,当然也可以根据其他的位,只要异或结果为1的位都可以。相同的元素必然划分为同一类。
这里就会划分为
001,101,101,111,111
010,110,110
然后大家都知道怎么做了,分别异或就好了。
那假如其他元素最后一位都相同,例如不是110而是1111怎么办,更简单了,会分成
001,101,101,111,111,1111,1111,
010
一样划分。
因为问题的关键在于将这两个残余的元素划分开,至于其他的元素,只有相同的划分到一起就好。
我写的代码如下
class Solution { public: vector<int> singleNumber(vector<int>& nums) { int sum = 0; for (int i = 0; i<nums.size(); i++) sum ^= nums[i]; int d = 2; while (true) { if (sum%d != 0) break; d = d * 2; } vector<int> vec1; vector<int> vec2; for (int i = 0; i<nums.size(); i++) { if (nums[i]/(d/2)%2 == 0) vec1.push_back(nums[i]); else vec2.push_back(nums[i]); } vector<int> ret(2,0); for (int i = 0; i<vec1.size(); i++) ret[0] ^= vec1[i]; for (int i = 0; i<vec2.size(); i++) ret[1] ^= vec2[i]; return ret; } };
最后会出错,因为最后一个例子中出现了负数,负数和正数的异或有些特殊。
这里总结一下负数的存储吧,我们都知道1表示为00000001
-1想象中应该为10000001
而事实上存的时候会先将符号位以外的取反为11111110再加一为11111111
所以-3就是10000011 -> 11111100 -> 11111101
异或的结果依然有效,两个元素的差异位也不会错,但是在nums[i]/(d/2)%2 == 0 这个判断会出问题,例如-3/8 = 0 按理倒数第三位应该为0,而事实上却为1.
看看别人的代码吧
vector<int> singleNumber(vector<int>& nums) { if (nums.size() < 2)return vector<int>(); else if (nums.size() == 2)return nums; int all = 0; for (auto num:nums) all ^= num; int flag = 0x01; while (true) { if (flag & all)break; flag <<= 1; } int res1 = 0, res2 = 0; for (auto num : nums) { if (num & flag) res1 ^= num; else res2 ^= num; } vector<int> result; result.push_back(res1); result.push_back(res2); return result; }
他使用的是一个flag做掩码,判断的时候用这个数字和flag与操作,看那一位到底是什么即可。
相关文章推荐
- python自我输出源程序
- CF 369C . Valera and Elections tree dfs 好题
- Linux下使用云笔记
- 区间赋值状态压缩线段树
- DLL导出函数和类 之 __declspec(dllexport)
- 查询语句实例
- Zookeeper 简单操作
- 近期打算整理的几篇文章
- javaScript实现动态取得不同的验证码
- 内省(反射)
- 2049 不容易系列之(4)——考新郎【错排+排列组合】
- latex简历
- Qt 常用类 (10)—— QDialog
- 对话框--QDialog(自定义对话框简单实例)
- HDU 4081Qin Shi Huang's National Road System(最小生成树+最小瓶颈路)
- XCODE6 提交至 App Store
- 关于JDK配置环境变量的问题
- 20150824朴素贝叶斯.md
- 151. Reverse Words in a String
- RPG黑暗之光(3)EasyTouch插件的使用、角色控制、相机跟随、状态记录