数组中只出现一次的两个数字:最直观的想法是,使用res表示结果,使用umap存储元素以及元素出现的次数,然后遍历array数组,记录各元素以及各元素出现的次数,接着遍历umap,找到只出现过一次的元素,并将其加入到res中,最后由于res中只有两个元素,直接判断排序即可。

    vector<int> FindNumsAppearOnce(vector<int>& array) {
        vector<int> res;
        // 元素 元素出现的次数
        unordered_map<int,int> umap;
        for(int i=0;i<array.size();i++)
        {
            //第一次出现
            if(umap.find(array[i])==umap.end())
                umap[array[i]]=1;
            //第n次出现
            else
                umap[array[i]]++;
        }
        // 遍历寻找只出现过一次的元素
        for(auto item:umap)
            if(item.second==1)
                res.push_back(item.first);
        // 两个元素 非降序排序
        if(res[0]>res[1])
            swap(res[0],res[1]);
        return res;
    }

优化:上述方法好像是较为通用的解题思路,但是有没有注意到,题目中特意说明,其他元素均出现两次,这是不是给我们的一个提示呢?位运算!异或运算!如果两个数相同,那么其位运算的结果为0,也就是说,如果只有一个只出现一次的数字时,其余均是出现两次时,我们可以将全部的数进行异或运算,那么最后得到的数字就是只出现一次的数字啦!可是,该题中有两个只出现一次的数字哎,这个怎么解决呢?尝试分组?将两个只出现一次的数字a和b分到两个不同的组中,且其他数字成对成对的被划分到不同的组,那么怎么分组呢?a和b的结果如果二进制的某一位为1,说明a和b对应位数不同,那么找到不同的这一位,然后以这一位是否为1来划分成两个数组,其中相同的数字自然会被划分到一边,而且a和b也会刚好被分开。总结下来具体的做法如下:首先遍历整个数组,将每个元素逐个异或运算,得到a异或b的结果;然后找到a异或b结果中第一位不相同的位,将所有元素分成两组;遍历整个数组对分开的数组单独进行异或;最后按照非降序次序输出。

vector<int> FindNumsAppearOnce(vector<int>& array) 
{
    // 结果数组 2个数 初始均为0
    vector<int> res(2,0);
    //遍历数组得到a^b
    int awb=0;
    for(int i=0;i<array.size();i++)
       awb^=array[i];
    // 找到两个数不同的一位 k表示不同那一位对应的数
    int k=1;
    while((k&awb)==0)
       k<<=1;
    // 遍历数组进行分类
    for(int i=0;i<array.size();i++)
    {
        if((k&array[i])==0)
           res[0]^=array[i];
        else
           res[1]^=array[i];
    }
    // 非降序次序
    if(res[0]>res[1])
       swap(res[0],res[1]);
    return res;
}