第一周

题目要求:

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字

看到有同学做了“选取奇数个数的数字”的题目,但是题目为
“一个整型数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字”
可以采用排序的方法求解,让数字成对出现,但是排序的算法最优时间复杂度是 O(nlog2n),也可以采用异或求解,利用异或的方法,可以让相同的两个数字相互异或消除,达到求解目的。
例:a[100] = {7,1,2,3,1,2,3,4,4}

#include "stdio.h"

int number(int a[], int n) {
    int i;
    int result = 0;
    for (i = 0; i<n;i++) {
        result ^= a[i];
    }
    return result;
}

int main(void) {
    int a[100] = {7,1,2,3,1,2,3,4,4};
    printf("%d\n",number(a, 9));
}

\color{red}{时间复杂度:O(n)}

但是如果结果有两个只出现一次的数字时,又该如何求解?
例:a[100] = {7,6,1,2,3,1,2,3,4,4}
结果会出现7和6的位相与后的结果 1,而不是7和6。

做题思路:

按照正常思路最终结果是求出a^b的值,为了求那两个奇数个的数,可以通过a = (a^b) ^ b 和 b = (a^b) ^ a来求解a和b, (a ^ b)已知,剩下的就是通过(a ^ b)想办法求出a和b的数字了。
①:求(a ^ b)
②:利用(a ^ b)求a,b
例中数组{7,6,1,2,3,1,2,3,4,4}求得的(a ^ b)为 7^6,二进制表示为0111和0110,所以(a ^ b)的结果会求得0001,然后我们要通过0001来分析。
首先出现位为1的可能就是位不相等异或出来的,可以将数组分为两个子数组,我们把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现两次。
如:a[100] = {7,6,1,2,3,1,2,3,4,4} 可变成{0111,0110,0001,0010,0011,0001,0010,0011,0100,0100}
分成两个子数组分别为a = {\color{orange }{0111}, 000\color{red}{1},001\color{red}{1},000\color{red}{1},001\color{red}{1}}(通过(a ^ b)= 0001获得所有结尾为\color{red}{1}的数)和b = {\color{orange}{0110},0010,0010,0100,0100},将子数组内元素相异或,即求得a和b

#include "stdio.h"
//获得(a ^ b)上的第一个位为1的位置
int FindFirstBitls1(int num) {
    int indexBit = 0;
    while ((num & 1) == 0) {
        num = num >> 1;
        ++ indexBit;
    }
    return indexBit;
}
//判断数组中的元素是否指定的位为1
_Bool IsBit1(int num, int indexBit) {
    num = num >> indexBit;
    return (num & 1);
}

void number(int array[], int n, int a, int b) {
    int i,j;
    int result = 0;
    for (i = 0; i<n;i++) {
        result ^= array[i];
    }
    int indexOf1 = FindFirstBitls1(result);
   a = b = 0;
    for (j = 0; j<n; ++j) {
        if(IsBit1(array[j], indexOf1))     //位为1,存入a数组
            a ^= array[j];
        else                               //否则,存入b数组
            b ^= array[j];
    }
    printf("%d\n",a);
    printf("%d\n",b);
}

int main(void) {
    int array[112] = {6,1,2,3,1,2,3,4,4,7};
    int a,b;
    number(array, 10, a, b);
}

\color{red}{时间复杂度:O(n)}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。