标签:
思路:先看一个简单的实例,若是找数组中只出现一次的一个数,其它的数都出现两次,直接对数组元素进行位异或就可以得到数组中只出现一次的一个数。本题中,找数组中只出现一次的两个数,则要将数组分成2个子数组,每个子数组中仅存在出现一次的一个数。关键就在于分组的标准,而对数组中所有的元素进行异或,得到的是这个数的异或。这个结果不为0,则一定存在某一个数字的一位为1,另一个数字中的某位为0,这样异或的结果才不为0。因此分组的标准是对数组元素全部进行异或的结果中首位为1的那一位(假设是第N位)。然后以这个数与数组中元素进行与运算,进行分组。数组元素第N位为1的分一组,为0为另一组。在每个子数组中进行全部异或,最终可以得出数组中只出现一次的两个数。
1 #include "stdafx.h" 2 3 unsigned int FindFirstBitIs1(int num); 4 bool IsBit1(int num, unsigned int indexBit); 5 6 void FindNumsAppearOnce(int data[], int length, int* num1, int* num2) 7 { 8 if(data == NULL || length < 2) 9 return; 10 11 int resultExclusiveOR = 0; 12 for(int i = 0; i < length ; ++ i) 13 resultExclusiveOR ^= data[i]; 14 15 unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR); 16 17 *num1 = *num2 = 0; 18 for(int j = 0; j < length ; ++j) 19 { 20 if(IsBit1(data[j], indexOf1)) 21 *num1 ^= data[j]; 22 else 23 *num2 ^= data[j]; 24 } 25 } 26 27 // 找到num从右边数起第一个是1的位 28 unsigned int FindFirstBitIs1(int num) 29 { 30 int indexBit = 0; 31 while( ((num & 1) == 0) && (indexBit < 8*sizeof(int)) ) 32 { 33 num = num >>1; 34 ++ indexBit; 35 } 36 37 return indexBit; 38 } 39 40 // 判断数字num的第indexBit位是不是1 41 bool IsBit1(int num, unsigned int indexBit) 42 { 43 num = num >> indexBit; 44 return(num & 1); 45 } 46 47 int main() 48 { 49 int data[] = {2, 4, 3, 6, 3, 2, 5, 5}; 50 int length = sizeof(data) / sizeof(int); 51 52 int result1, result2; 53 FindNumsAppearOnce(data, length, &result1, &result2); 54 55 printf("%d %d\n", result1, result2); 56 57 return 0; 58 }
标签:
原文地址:http://www.cnblogs.com/sankexin/p/5635970.html