一組數字中只有兩個數單獨出現,其他數成對出現,找出這兩個數

在寫過一個數字單獨出現後,知道全體異或後成對出現的數字將抵消,這次將得到兩個單獨出現的數字的結果

得到兩個單獨出現數字異或的結果後,把兩個數字分離出來就可以了,但通過x^y得到其中一個數字需要另一個數字,無法分離,但是我們知道異或爲1的位兩個數該位必然不同,通過這個比特位把數字分爲兩組,再分別異或就可以得到這兩個數了

void check_num(int *arr, int sz,int *x,int *y)
{
    *x = 0;
    *y = 0;
    int n = 0;
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        n ^= arr[i];//得到兩個單獨出現的數字異或的結果
    }
    n = n & ((n - 1)^-1);//取出第一個非零比特位
    //(n-1)把第一個非零比特位置零,^1按位取反[-1的補碼位爲全1]保留第一個剛置零的比特位,
    //過程見http://blog.csdn.net/mzx1317557721/article/details/70495637
    for (i = 0; i < sz; i++)
    {
        if (arr[i] & n)
            *x ^= arr[i];
        else
            *y ^= arr[i];
    }
}
  • arr爲數組首元素地址
  • sz爲數組元素個數
  • x,y爲接收兩個單獨出現數字的變量

當然也可以暴力求解,如果想不出好方法就只能遍歷兩次了

網上還有一種通用方法,當數組內的數字都比較小的時候可以用

建立一個大於數組內最大數字的數組,初始化爲0,當某個數字出現一次的時候,對應下標數字加一,最後某個數字出現幾次看下標就好了

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//調用函數
void first_num(int * str)
{
    assert(str);        //斷言,判斷傳進的數組指針是否有效,用以拋出異常。
    int asc[10] = { 0 };    //創建一個十個元素的數組,
    //因爲原數組元素的大小都只爲0~9的元素,可根據需要自行設定大小。
    int i = 0;
    for (i = 0; i<10 ; i++)
    {
        asc[str[i]]++;    //將原數組的元素作爲新建數組的下標,並自增。
        //如果原數組有相同元素,說明在新建數組對應的位置處的值會不斷加1。
    }
    printf("出現一次的兩數爲:\n");
    for (i = 0; i<10; i++)
    {
        if (asc[str[i]] == 1)    //輸出條件,只要新建數組的值仍爲1,說明原數組中該元素只有一個。
        {
            printf("%d ", str[i]);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章