一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。找出这两个数字

方法1:遍历,查找

定义一个临时变量k=0,不断将数组每个数与数组每个元素比较,如果两个数相等k++,然后判断k是否等于1。如果为1,则这个数在数组只出现一次;如果k=2,说明出现两次。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
void find_num(int arr[], int sz)
{
    int i, j, k = 0;
    for (i = 0; i < sz; i++)
    {
        k = 0;
        for (j = 0; j < sz; j++)
        {
            if (arr[j] == arr[i])
                k++;
        }
        if (k == 1)
            printf("单数为 %d\n", arr[i]);
    }
    printf("\n");
}
int main()
{
    int arr[] = { 1, 2, 3, 4, 1, 2, 3, 5 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    find_num(arr, sz);
    system("pause");
    return 0;
}

方法2:
思路:
数组不全成对出现,有2个单数。 {3,5,7,3,5,11}
此时,每个数依次异或的结果为:0011^0101^0111^0011^0101^1011=1100。
因为后边两位是0,则说明两个单数是从倒数三位不同的。然后让每个数右移两位 则数据会变为
3: 0000
5: 0001
7: 0001
3: 0000
5: 0001
11:0010
然后把末尾为零的依次异或 在这组数据里是3 3 11; 结果得到单数11。
把末尾为1的依次异或 在这组数据里是5 7 5;结果得到单数7。

void find_num(int *p, int sz)
{
    int i = 0;
    int n = 0;
    int count = 0;
    int num1 = 0;
    int num2 = 0;
    for (i = 0; i < sz;i++)//将所有数异或
    {
        n ^= *(p + i);
    }
    while (!(n & 1))//判断异或结果有多少个0
    {
        count++;
        n >>= 1;
    }
    for (i = 0; i < sz; i++)
    {
        n = *(p + i) >> count; //所有数异或结果后面有几个0,
                               //每个数依次往右移动几位
        if (n & 1)
            num1 ^= *(p + i); //把末位为1的数依次异或
        else
            num2 ^= *(p + i); //把末位为0的数依次异或
    }
    printf("两个单数为 %d %d\n", num1, num2);
}
int main()
{
    int arr[] = { 1, 2, 3, 4, 1, 2, 3, 5 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    find_num(arr, sz);
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sifanchao/article/details/80041002