欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

从103个数中找到出现一次的那三个数

程序员文章站 2022-03-01 17:49:44
...

1、从101个数中找到出现一次的那1个数?

eg:[5,7,6,7,5] 找到6

//101
void demo01() {
    int arr[5] = { 5,7,6,7,5 };
	
    int result;
    result = 0;
    for (int i = 0; i < 5; i++) {
        result ^= arr[i];
    }
    
    printf("出现一次的那个数=%d\n", result);
}

通过异或操作,就可以找到唯一出现的那个数;

2、从102个数中找到出现一次的那2个数?

eg:[5,7,6,7,5,8] 找到 6,8

//101
int demo01(int arr[]) {
    //int arr[5] = { 5,7,6,7,5 };

    int result;
    result = 0;
    for (int i = 0; i < 6; i++) {
        result ^= arr[i];
    }
    
    //printf("出现一次的那个数=%d\n", result);
    return result;
}

//102
void demo02() {
    
    int arr[6] = { 5,7,6,7,5,8 };
    int flag = demo01(arr);
    int split_val = flag & (-flag);
    printf("%d\n", split_val);
    int res1, res2;
    res1 = 0; res2 = 0;    
    for (int i = 0; i < 6; i++) {
        if (arr[i]&split_val) {
            res1 ^= arr[i];
        }else {
            res2 ^= arr[i];
        }
    }
    printf("第一个数=%d,第二个数=%d\n", res1,res2);
}

1、通过所有值得异或就可以找到在两个不同数之间的不同;
2、通过flag & (-flag)操作可以找到所有值得异或结果的最低位的1;
3、通过和最低位的1与操作,可以把两个不同的数分开;一个为真,一个为假;

3、从103个数中找到出现一次的那3个数?

eg: [5,7,6,7,5,8,9]找到6,8,9

//102
void demo02(int arr[],int even,int odd) {
    
    int split_val = even & (-even);
    //printf("%d\n", split_val);
    int res1, res2;
    res1 = 0; res2 = 0;    
    for (int i = 0; i < 7; i++) {
        if (arr[i]&split_val) {
            res1 ^= arr[i];
        }else {
            res2 ^= arr[i];
        }
    }
    if (split_val& odd) {
        res1 ^= odd;
    }else {
        res2 ^= odd;
    }
    printf("第二个数=%d,第三个数=%d\n", res1,res2);
}

//103
void demo03() {
    int arr[7] = { 5,7,6,7,5,8,9 };
    int res1, res2,count1,count2;
    int flag;
    flag = 1;
    for (int i = 0; i < 32;i++) {
        res1=res2=count1=count2 = 0;
        for (int j = 0; j < 7; j++) {
            if (flag&arr[j]) {
                res1 ^= arr[j];
                count1++;
            }else {
                res2 ^= arr[j];
                count2++;
            }    
        }
        //判断偶数是否大于0
        if (count1 % 2 == 0 && res1!=0) {
            printf("第一个数=%d", res2);
            demo02(arr, res1, res2);
            break;
        }
        else if (count2 % 2 == 0 && res2 != 0) {
            printf("第一个数=%d", res1);
            demo02(arr, res2, res1);
            break;
        }
        //如果没找到 0 3 
        flag << 1;
    }
}

1、首先,使用暴力法,从1开始,每次向左移动1位二进制位,到32位也就是移动31位;
2、就把把那三个单独的数分成2堆,只有两种情况;奇数堆:偶数堆 = 3 :0 或 1:2;
3、只需要判断偶数堆的异或操作不为0,也就是说是1:2这种情况;就找到了在奇数堆中的一个单数;
4、通过demo02函数;思想和第2题一样,但是因为有103个数,所以第三个单数会被分配到其中一边;
5、我们需要判断这个数,是在奇数堆还是在偶数堆,通过split_val & odd判断是在那一边,就可以在异或一次,就可以消除这个数;