数组中只出现一次的两个数字:最直观的想法是,使用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;
}



京公网安备 11010502036488号