大致问题描述:
问题1:给一组整数,里面有且只有1个数出现了奇数次,请找出这个数?
问题2:给一组整数,里面有且只有2个数出现了奇数次,请找出这两个数?
思路引导:
此处需要用到布尔运算中的“异或”。a与b进行异或运算(a^b),是当a与b不相同时为真。即a=0,b=1或a=1,b=0时为真。
可推导及验证:a^a = 0,a^0 = a => a^b^a = b^a^a = b^0 = b,
解答1:
将该组数依次进行“异或运算”,得出的值即为出现了奇数次的1个数。
假设:intList={a,b,c,...,c,b,a,t} ,那么 a^b^c^...^c^b^a^t = t^a^a^b^b^c^c... = t ^ = t 即可找出出现了奇数次的唯一一个数t
简单示例代码:
1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 int intList[7] = {10, 3, 15, 4, 15, 4, 10}; 8 int t = 0; 9 for (int i = 0; i < 7; ++i) 10 { 11 t = t ^ intList[i]; 12 } 13 cout << t << endl; 14 return 0; 15 }
解答2:
既然出现在了一起,那么肯定也是要用到“异或”操作的啦。
将该组数依次进行“异或运算”,根据上述的推导也不难看出,最后的结果为出现了奇数次的两个数的异或值a^b。
现在关键需要的是怎么才能将a和b从a^b中分离出来。直接给思路好了,我是不知道怎么推出来。
a与b既然不相同,那么他们的对应二进制位中肯定不相等的,那么我们找出一个不相等的那一位,将这组数中所有的数分成a阵营,b阵营,再对着两个阵营进行组内的“异或”运算,就变成了问题1了。
1 #include <iostream> 2 #include <cmath> 3 4 using namespace std; 5 6 int main() 7 { 8 int intList[8] = {10, 3, 15, 4, 15, 4, 10, 8}; 9 int t = 0; 10 for (int i = 0; i < 8; ++i) 11 { 12 t = t ^ intList[i]; 13 } 14 15 int k = 0; 16 for (int i = 1; i < 8; ++i) 17 { 18 if (t % (int)pow(2, i) != 0) 19 { 20 k = i; 21 break; 22 } 23 } 24 25 int a = 0, b = 0; 26 int mi = (int)pow(2, k - 1); 27 28 for (int i = 0; i < 8; ++i) 29 { 30 if ((intList[i] & mi) == 0) 31 { 32 a ^= intList[i]; 33 } 34 else 35 { 36 b ^= intList[i]; 37 } 38 } 39 40 cout << a << ‘ ‘ << b << endl; 41 42 return 0; 43 }
原文:https://www.cnblogs.com/lxnow/p/13405650.html