【剑指offer】59.数组中只出现一次的两个数字
总目录:
1.问题描述
一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
数据范围:数组长度 2≤n≤1000,数组中每个数的大小0<val≤1000000
要求:空间复杂度 O(1),时间复杂度 O(n)
要求:空间复杂度 O(1),时间复杂度 O(n)
提示:输出时按非降序排列。
2.问题分析
1哈希
迭代元素,查看哈希表中是否有该元素,有则从哈希表中删去,没有则插入,最后将哈希表中的内容导出并排序
2位比较
数字异或自身=0,且异或满足交换律
将所有数字异或在一起,得到的是那两个独立数字的异或值,
问题是如何将这两个数字分开?这两个数字至少有1位不同,用那一位数字将整个集合分成两部分,两部分内的数字全部异或在一起,将分别得到2个独立数字。(太巧妙了)
3.代码实例
哈希
1 class Solution { 2 public: 10 vector<int> FindNumsAppearOnce(vector<int>& array) { 11 unordered_set<int> set; 12 for (int i = 0; i < array.size(); i++) { 13 if (set.find(array[i]) != set.end()) { 14 set.erase(array[i]); 15 } else { 16 set.insert(array[i]); 17 } 18 } 19 20 vector<int> ret; 21 for (auto j :set) { 22 ret.push_back(j); 23 } 24 if(ret[0]>ret[1]){ 25 swap(ret[0],ret[1]); 26 } 27 28 return ret; 29 } 30 };
位运算
1 class Solution { 2 public: 3 /** 4 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 5 * 6 * 7 * @param array int整型vector 8 * @return int整型vector 9 */ 10 vector<int> FindNumsAppearOnce(vector<int>& array) { 11 // 先将全部数进行异或运算,得出最终结果 12 int tmp = 0; 13 for (int num : array) { 14 tmp ^= num; 15 } 16 17 // 找到那个可以充当分组去进行与运算的位 18 // 从最低位开始找起 19 int mask = 1; 20 while ((tmp & mask) == 0) { 21 mask <<= 1; 22 } 23 24 // 进行分组,分成两组,转换为两组 求出现一次的数字 去求 25 int a = 0; 26 int b = 0; 27 for (int num : array) { 28 if ((num & mask) == 0) { 29 a ^= num; 30 } else { 31 b ^= num; 32 } 33 } 34 35 //排序 36 vector<int> ret; 37 ret.push_back(a < b ? a : b); 38 ret.push_back(a < b ? b : a); 39 return ret; 40 } 41 };