找出数组中只出现一次/两次/三次的数字,而其他数字都出现偶数次

来源:互联网 发布:宾馆前台收银软件 编辑:程序博客网 时间:2024/04/30 10:53

原题描述:

一个数组中有一个/两个/三个数字只出现一次,其他数字都出现了偶数次。请找出一个/两个/三个只出现一次的数字?


具体实现如下:(三个出现一次的数字,有些乱,待优化)三种,均已测试通过。

#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;// find the three different number in the int array where the other number is exit double//1.找出数组中的只出现一次的一个数字//####数组中所有数据异或后得到的值即为所求。(相同值异或为零)//2.找出数组中的只出现一次的两个数字//####只要能想办法将这两个数字放在两个数组中,而这两个数组由原数组分出,并且每一个数组除了这个数字外都是成对出现的(即和原数组组成相似)//####所有数字异或后,按照所得值的二进制数中其中一位为1的位为标志,将数组分成两组,然后按1方法,找出两组中的数字。//3.找出数组中的只出现一次的三个数字//####这个要借助到1和2的方法,首先要想办法将三个数字分在两个数组中,而分的标准和2有些相似,也是以某一位是否为1为标志//####但是有一种情况是,三个数的某一位全为1,这是三个数还是会分到同一数组中,没有达到将他们分在两个数组的目的,所以要找可以将他们分在两个数组的标志位。//####我是通过判断查找的,当他们又被分到同一组时,则将找到的这个标志位置0,同时查找下一个是1的标志位,然后再分,知道找到能将他们分到不同组的标志位,//####(这个标志位是肯定存在的,因为他们三个数字各不相同)//####三个位异或为1的情况只有一下几种://  一:0 0 0 0 1 1 1 1//  二:0 0 1 1 0 0 1 1//  三:0 1 0 1 0 1 0 1//异或:0 1 1 0 1 0 0 1void FindOneNum(int array[],int length,int &num){    if(length < 2)        return ;    for(int i = 0; i<length ;i++)    {        num ^= array[i];    }}int FindFirstBitIs1(int num);bool IsBitIs1(int num, int n);void FindTwoNum(int array[],int length, int &num1,int &num2){    if(length < 2)        return ;    int num = 0;    for(int i = 0; i<length ;i++)    {        num ^= array[i];    }    unsigned int n = FindFirstBitIs1(num);    num1 = num2 = 0;    for(int j= 0; j<length; j++)    {        if(IsBitIs1(array[j],n))        {            num1 ^= array[j];        }        else        {            num2 ^= array[j];        }    }}void FindThreeNum(int array[],int length, int &num1, int &num2, int &num3){    if(length < 2)        return ;    int num = 0;    for(int i = 0; i<length ;i++)    {        num ^= array[i];    }    unsigned int n = FindFirstBitIs1(num);    int n1 = 0, n2=0;    int number1 = 0, number2 = 0;    //申请两个数组,存放分开的元素    int *array1 = new int[length];    int *array2 = new int[length];    while(n<32)    {        int k = 0,t=0;//实现分开的数组的计数        for(int j= 0; j<length; j++)        {            if(IsBitIs1(array[j],n))            {                array1[k++] = array[j];                number1 ^= array[j];                n1++;            }            else            {                array2[t++] = array[j];                number2 ^= array[j];                n2++;            }        }        //三个数在该位上都为1,则三个数被分到同一个组中,当三个没有被分到同一个组中的时候。        if((number1 != 0)&&(number2 != 0))        {            if(n1%2==0)            {                FindTwoNum(array1,n1,num1,num2);                num3 = number2;            }            else            {                FindTwoNum(array2,n2,num1,num2);                num3 = number1;            }            break;        }        //可能三个数的这个这以为上都为1,则判断下一个异或为1的位,知道找到,三个数中所判断位只有一个的是1,另外两个的是0.        //肯定能找到这样的一位,因为,三个数不可能完全相同。        else        {            num = num ^ (1<<n);            n = FindFirstBitIs1(num);            continue;        }    }    delete[] array1;    delete[] array2;}int FindFirstBitIs1(int num){    int n = 0;    while(((num&1) == 0)&&(n < 32 ))    {        num = num >> 1;        n++;    }    return n;}bool IsBitIs1(int num, int n){    num = num >> n;    return (num & 1);}int main(){    int array[]={1,1,2,2,3,3,3,5,5,6,7,7,10,8,8,9,9};    int length = sizeof(array)/sizeof(int);    //int num = 0;    //FindOneNum(array,length,num);    //printf("%d",num);    int num1= 0 ;    int num2 = 0;    //FindTwoNum(array, length, num1, num2);    //printf("%d  %d",num1,num2);    int num3=0;    FindThreeNum(array,length,num1,num2,num3);    printf("%d %d %d",num1,num2,num3);    return 0;}

原创粉丝点击