数组中两个只出现一次的数字

题目:

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字,要求:时间复杂度为O(n),空间复杂度O(1)

测试样例:

输入:

8

{2,4,3,6,3,2,5,5}

输出:

4,6

解法:

使用异或解决问题:一个数异或自己等于0,异或其他数 != 0,如果是一个数字,那么一趟遍历数组异或之后的结果就是我们要的;而现在是2个数据,那么我们需要仔细考虑怎样将两个数字分开:

首先:将所有的数进行异或,得到一个结果不等于0的数字,因此这个结果数字在二进制位上必定最少有一位为1(因为那2个数不一样),我们从该结果的右边开始选择一个为1的位,记为第n位(这一位为1,那么就意味着第一个数的此位置上为1 ,第二个数此位置上肯定为0,或者反之,不然不可能异或 != 0);那么根据这一位的特性,将数组元素分成两个子数组,第一个子数组的每个数字的第n位为1,而第二个子数组中每个数字的第n位都是0;由于我们分组的标准是数字中的某一位是0还是1,那么出现了两次的数字肯定被分到了同一个数组;然后分别对这两部分进行再次异或得到两个数;

代码实现

//查找整数number最右边是1的位
int findFistBitIs1(int number)
{
    int index = 0;
    while (((index & 1) == 0) && index <= sizeof(int) * 8)
    {
        number >>= 1;
        ++ index;
    }

    return index;
}

//测试number的从右边数第indexBit位是否为1
int isBit1OnIndex(int number, int indexBit)
{
    int testNumber = 1 << indexBit;
    return (number & testNumber);
}

int main()
{
    freopen("input.txt","r",stdin);
    int n;
    cin >> n;
    int *array = new int[n];
    for (int i = 0; i < n; ++i)
    {
        cin >> array[i];
    }

    int testNumber = 0;
    for (int i = 0; i < n; ++i)
    {
        testNumber ^= array[i];
    }

    int indexOf1 = findFistBitIs1(testNumber);

    int ans1,ans2;
    ans1 = ans2 = 0;
    for (int i = 0; i < n; ++i)
    {
        if (isBit1OnIndex(array[i],indexOf1))
        {
            ans1 ^= array[i];
        }
        else
        {
            ans2 ^= array[i];
        }
    }

    cout << ans1 << " " << ans2 << endl;

    delete []array;
}
时间: 2024-10-04 23:04:20

数组中两个只出现一次的数字的相关文章

【编程题目】找出数组中两个只出现一次的数字 ★★(自己没做出来)

61.找出数组中两个只出现一次的数字(数组)题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是 O(n),空间复杂度是 O(1). 思路:瞄到了一眼提示,说是位运算. 根据异或的运算性质: a ⊕ b ⊕ a = b 把所有的数字都异或一遍得到的结果就是 那两个只出现一次的数字异或的结果. 可怎么分出那两个数字就卡住了. 看了下网上答案,要根据得到的异或值把数字分为两组,再对每一组异或就可以得到这两个数字了! 代码如下: /* 61

算法题:找出整数数组中两个只出现一次的数字

问题:一个整数数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度为O(n),空间复杂度为O(1). 分析:这是一个很新颖的关于位运算的题目. 首先考虑这个问题的一个简单版本:一个整数数组里除了一个数字之外,其他的数字都出现两次,请写程序找出这个只出现一次的数字. 这个问题的突破口在哪?题目中数组的性质是只有一个整数出现一次,其他的都出现两次.这样的话就使我们想到了异或运算的性质:任何一个数字异或它自己都等于0.也就是说如果从头到尾依次异或数组中的每

找出数组中两个只出现一次的数字

题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 还是理解不够深刻. 这题的主要思路还是之前的数组中只出现一次的数字的那种模式,一次遍历加上异或运算.那么这个异或的值肯定是这两个只出现一次的数字的相异或的值.那么这个值的二进制表现形式中的1的结果就表示这两个数字在该bit位上不一样.那么通过此举,我们可以以这个bit位是否为1来从整个数组中把这两个只出现一次的数字分开. 通过此举,别的出现两次的数字

找出数组中两个只出现一次的数字 【微软面试100题 第六十一题】

题目要求: 一个整型数组里除了两个数字机之外,其他的数字都出现了两次. 请写程序找出这两个只出现一次的数字.要求时间复杂度O(N).空间复杂度O(1). 参考资料:剑指offer第40题. 题目分析: 已知: 1.两个相同的数字异或的结果为0,即a^a = 0. 2.两个不相同的数字异或的结果的二进制中某一位为1,则这两个数字的二进制中对应位一个为0,一个为1.如3^2 = 1,对于最低位的二进制,3的最低位二进制为1,2的最低位二进制位0,则结果1的最低位二进制肯定为1. 假设原数组中只出现一

剑指offer 面试题40—数组中两个只出现一次的数字

题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度O(n),空间复杂度O(1). 基本思想: http://blog.csdn.net/wtyvhreal/article/details/44260321 #include <iostream> using namespace std; int Find1(int n)//从低位开始找第一个1的位置 { int index=0; while((n&1)==0 &&a

找出数组中两个只出现一次的数字!

实现代码: 1.PHP实现: <?php     $arr=array(1,1,5,3,2,2);          //因为每个元素都需要分别和其他的元素进行比较     //所以需要双重循环     for($i=0;$i<count($arr);$i++){                  for($j=0;$j<count($arr);$j++){                      //此处目的是避免数组元素和自己进行比较             if($i != $j

面试题1:找出一个数组中三个只出现一次的数字

version1: 找出一个数组中一个只出现一次的数字,其他数字都出现两次:将所有数字异或,得到的结果即为只出现一次的. version2: 找出一个数组中两个只出现一次的数字,其他数字都出现两次:将所有数字异或,得到的结果即为x=a^b, index为x中第一个为1的位,则a 和b中第index为必然有一个为1,有一个为0.据此将所有数据分为两组,一组的第index为都为1,另一组第index为都为0,第一组数字异或得到a,第二组数字异或得到b. 时间复杂度为o(n),空间复杂度为o(1).

面试题---找出数组中两个只出现一次的数

题目描述:给一个数组,里面有两个数只出现一次,其它的数都出现两次,请找出这两个数: 样例:输入 2 4 2 7 4 9 输出 7 9 思路:假定要找出的这两个数为x.y   把所有的数异或,结果是x与y异或的值,那么肯定不为0,那么这个值的二进制至少有一位为1,也就是说x和y的二进制在这一位上必定一个为0,一个为1,那么可以根据这一位把这个数组分成两个数组,x和y在不同的数组里,接下来对每个数组直接异或出的值就是结果了: 代码如下: #include <iostream> #include &

其他数出现两次的数组中两个只出现一次数

#include <stdio.h> #include <stdlib.h> /* 有102个整数, 其中有50个数出现了两次, 2个数出现了一次, 找出出现了一次的那2个数. */ /* 思路: 所有数异或得到两个单独数a,b的异或值c, 指出c为1的某位. 根据pos位为1或者为0将数组划分为两个组, 再分别对这两个组进行异或, 即可得到:a,b. */ /* 注:结构体要放在函数声明前 */ typedef struct { int num1; int num2; }TwoN