剑指Offer 数组中只出现一次的数字

时间:2022-09-28 14:33:12

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。   思路: 因为有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);