找出数组中两个只出现一次的数字 【微软面试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.

  假设原数组中只出现一次的两个数为a和b,则,原数组所有元素异或的结果c,即为a^b的结果(因为其他异或都为0),即a^b = c;

  根据已知条件2,我们从c中找到其二进制中为1的位,把原数组分成两个部分X和Y(a和b分别在X和Y中,且X和Y中分别都是只有一个数字出现一次,其他数字出现两次),则X中的所有元素异或的结果肯定为a,Y中所有的元素异或的结果肯定为b,即为所求。

代码实现:

  

#include <iostream>

using namespace std;
const int N = 6;
bool FindNumsAppearOnce(int data[],int len,int &num1,int &num2);

int main(void)
{
    int data[N] = {4,2,6,2,4,5};
//    int data[N] = {4,2,6,2,4,6};
    int num1,num2;
    if(FindNumsAppearOnce(data,N,num1,num2))
    {
        cout << "num1 = "<< num1 << ",num2 = " << num2 << endl;
    }
    else
        cout << "不满足情况" << endl;
    return 0;
}
unsigned int FindFirstBitIs1(int num)
{
    int index = 0;
    while((num&1)==0 &&(index<8*sizeof(int)))
    {
        num >>= 1;
        ++index;
    }
    return index;
}
bool IsBit1(int num,unsigned int index)
{
    num >>= index;
    return (num&1);
}
bool FindNumsAppearOnce(int data[],int len,int &num1,int &num2)
{
    if(data==NULL || len<2 || ((len&0x01)==1))
        return false;
    int result =0;
    for(int i=0;i<len;i++)
        result ^= data[i];
    if(result==0)
        return false;
    unsigned int index = FindFirstBitIs1(result);

    num1 = num2 = 0;
    for(int j = 0;j<len;j++)
    {
        if(IsBit1(data[j],index))
            num1 ^= data[j];
        else
            num2 ^= data[j];
    }
    return true;
}

  

时间: 2024-11-05 14:55:57

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

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

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

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

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

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

实现代码: 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

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

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

经典算法学习——快速找出数组中两个数字,相加等于某特定值

这个算法题的描述如下:快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值.目前我假设数组中的都是各不相等的整数.这道题是我在一次面试中被问到的,由于各种原因,我没回答上来,十分尴尬.其实这道题十分简单,我们使用相对巧妙的方法来实现下.注意不使用两层循环的元素遍历.示例代码上传至:https://github.com/chenyufeng1991/SumTo100 . 算法描述如下: (0)首先对原数组进行排序,成为递增数组: (1)对排序后的数组头部i [0]和数组尾部j [n-1]

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

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

找出数组中两数之和为指定值的所有整数对

一,问题描述 给定一个整型数组(数组中的元素可重复),以及一个指定的值.打印出数组中两数之和为指定值的 所有整数对 二,算法分析 一共有两种方法来求解.方法一借助排序,方法二采用HashSet 方法一: 先将整型数组排序,排序之后定义两个指针left和right.left指向已排序数组中的第一个元素,right指向已排序数组中的最后一个元素 将 arr[left]+arr[right]与 给定的元素比较,若前者大,right--:若前者小,left++:若相等,则找到了一对整数之和为指定值的元素

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

题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字,要求:时间复杂度为O(n),空间复杂度O(1) 测试样例: 输入: 8 {2,4,3,6,3,2,5,5} 输出: 4,6 解法: 使用异或解决问题:一个数异或自己等于0,异或其他数 != 0,如果是一个数字,那么一趟遍历数组异或之后的结果就是我们要的;而现在是2个数据,那么我们需要仔细考虑怎样将两个数字分开: 首先:将所有的数进行异或,得到一个结果不等于0的数字,因此这个结果数字在二进制位上必定

剑指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