数组中只出现一次的数字

来源:互联网 发布:深圳云和数据招聘 编辑:程序博客网 时间:2024/05/05 14:21
/***********************************************************************题目:一个整型数组除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(N),空间复杂度为O(1)。***********************************************************************//*解题思路:由于其他数字都出现了两次,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消了。由于这两个数字肯定不一样,那么异或的结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1。我们在结果数字中找到第一个为1的位,记为第n位。现在我们以第n位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第n位都是1,而第二个子数组中每个数字的第n为都是0。由于我们分组的标准是数字中的某一位是1还是0,那么出现了两次的数字肯定被分配到同一个数组。因为两个相同的数字的任意一位都是相同的,我们不可能把两个相同的数字分配到两个子数组中去,于是我们已经把原数组分成了两个子数组,每个字数组都包含一个只出现一次的数字,而其他数字都出现了两次。我们已经知道如何在数组中找出唯一一个只出现一次的数字,因此到此为止所有的问题都已经解决了。举个例子:假设输入数组{2,4,,6,3,2,5,5}。当我们依次对数组中的每一个数字做异或运算之后,得到的结果用二进制表示是0010。异或得到结果中的倒数第二位是1,于是我们根据数字的倒数第二位是不是1分成两个数组。第一个子数组{2,3,6,3,2}中所有数字的倒数第二位都是0。接下来只要分别对这两个子数组求异或,就能找出第一个子数组中只出现一次的数字是6,而第二个子数组中只出现一次的数字是4。*/#include<stdio.h>unsigned int findFirstBitIs1(int num);bool IsBit1(int num, unsigned int indexBit);void findNumAppearOnce(int* data,int length,int* num1,int* num2){if(data == NULL || length<2)return;int resultExclusiveOR = 0;for(int i=0; i<length; ++i)resultExclusiveOR ^= data[i];unsigned int indexOf1 = findFirstBitIs1(resultExclusiveOR);*num1 = *num2 = 0;for(int j=0; j<length; ++j){if(IsBit1(data[j],indexOf1))*num1 ^= data[j];else*num2 ^= data[j];}}//找到所有数字异或后的结果,最先出现1的位置unsigned int findFirstBitIs1(int num){int indexBit = 0;while(((num & 1) == 0) && (indexBit < 8 * sizeof(int))){num = num>>1;++indexBit;}return indexBit;}//判断数字num上第indexBit位是不是为1。bool IsBit1(int num, unsigned int indexBit){num = num >> indexBit;return (num & 1);}void test(){const int length = 8;int arr[length] = {2,4,3,6,3,2,5,5};int num1 = 0;int num2 = 0;findNumAppearOnce(arr,length,&num1,&num2);printf("%d\t%d\n",num1,num2);}int main(){test();return 0;}
==参考剑指offer
0 0
原创粉丝点击