剑指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);

 

 

 

posted @ 2016-11-30 10:58  SeeKHit  阅读(509)  评论(0编辑  收藏  举报