剑指Offer 数组中只出现一次的数字
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路:
因为有2个数字只出现了一次,而其他的数字都是2次,可以通过异或运算,得到最后这2个只出现一次的数字的 异或结果值。这种值必然不为0。
然后找出这个数字二进制中,最低位为1的位数,必然那一位一个是0,一个是1。
通过这个条件将原数组分为2部分,分别异或,得到结果。
代码:
1 class Solution { 2 public: 3 void FindNumsAppearOnce(vector<int> data, int* num1, int *num2) 4 { 5 int res = 0, tag = 0; 6 if (data.empty()) 7 { 8 num1 = num2 = 0; 9 } 10 11 for (int i = 0; i < data.size(); i++) 12 { 13 res ^= data[i]; 14 } 15 16 for (; tag < 32; tag++) 17 { 18 if ((res & (1<<tag)) != 0) 19 break; 20 } 21 22 for (int i = 0; i < data.size(); i++) 23 { 24 if ((data[i] & (1 << tag)) == 0) 25 *num1 ^= data[i]; 26 else 27 *num2 ^= data[i]; 28 } 29 } 30 };
题2:
一个数组中有一个数字只出现一次。
思路:
直接遍历异或整个数组,得到的就是只出现一次的那个数字。
题3:
一个数组中,一个数字出现1次,其他都出现3 次
思路:
开辟一个位数的数组,遍历远数组记录所有元素的2进制,位数和。
遍历位数数组,将值除3取余,最后一个位数数组上留下来的就是最后这个只出现一次的数组。
代码:
1 public static int find1From3(int[] a){ 2 int[] bits = new int[32]; 3 int len = a.length; 4 for(int i = 0; i < len; i++){ 5 for(int j = 0; j < 32; j++){ 6 bits[j] = bits[j] + ( (a[i]>>>j) & 1); 7 } 8 } 9 int res = 0; 10 for(int i = 0; i < 32; i++){ 11 if(bits[i] % 3 !=0){ 12 res = res | (1 << i);