告诉你n个数

又是一道喜闻乐见的面试题,分三个难度

No.1

告诉你n个数,其中只有一个数只出现了一次,其他所有的数都出现了两次,求这一个数

一切都源于这道题,一道平凡的题由于巧妙了利用了异或的性质而大放异彩,解答:

int m = 0;
for(int i = 0; i < n; ++i){
    m = m ^ N[i];
}
return m;

No.2

告诉你n个数,其中有两个数只出现了一次,其他所有数都出现了两次,求这两个数

比刚才那道题难了一点,不过大同小异,依然是将左右数都异或一遍,剩下的数一定是这两个只有一个的数的异或

因为两个数不同,这个数一定不是0。这个数的二进制表示中必有一位是1,这两个数必定在这一位上有所不同。

将所有数分成两组,一组在该位上为0,一组在该位上为1

两组分别再进行异或,将求出两个数

No.3

告诉你n个数,其中只有一个数只出现了一次,其他所有的数都出现了三次,求这一个数

又难了一点点,需要用到按位非的运算,解答:

int ones = 0; // 出现一次的标志位
int twos = 0; // 出现第二次标志位
for(int i = 0; i < n; i++) {
    ones = (ones ^ A[i]) & ~twos; // 第一次出现的加上, 第二次出现的去掉, 第三次出现的不变
    twos = (twos ^ A[i]) & ~ones; // 第一次出现的不变, 第二次出现的加上, 第三次出现的去掉
}
return ones;

看着很难,本质就一句话,把已经出现两次的在ones中去掉,在twos中记录下来