第三十三题 输出容器中3个不同的数

来源:互联网 发布:淘宝网电子琴 编辑:程序博客网 时间:2024/06/06 09:57

题目:一个数组中有三个数字abc只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。

思路:如果我们把数组中所有数字都异或起来,那最终的结果(记为x)就是abc三个数字的异或结果(x=a^b^c)。其他出现了两次的数字在异或运算中相互抵消了。

我们可以证明异或的结果x不可能是abc三个互不相同的数字中的任何一个。我们用反证法证明。假设x等于abc中的某一个。比如x等于a,也就是a=a^b^c。因此b^c等于0,即b等于c。这与abc是三个互不相同的三个数相矛盾。

由于xabc都各不相同,因此x^ax^bx^c都不等于0

我们定义一个函数f(n),它的结果是保留数字n的二进制表示中的最后一位1,而把其他所有位都变成0。比如十进制6表示成二进制是0110,因此f(6)的结果为2(二进制为0010)。f(x^a)f(x^b)f(x^c)的结果均不等于0

接着我们考虑f(x^a)^f(x^b)^f(x^c)的结果。由于对于非0nf(n)的结果的二进制表示中只有一个数位是1,因此f(x^a)^f(x^b)^f(x^c)的结果肯定不为0。这是因为对于任意三个非零的数ijkf(i)^f(j)的结果要么为0,要么结果的二进制结果中有两个1。不管是那种情况,f(i)^f(j)都不可能等于f(k),因为f(k)不等于0,并且结果的二进制中只有一位是1

于是f(x^a)^f(x^b)^f(x^c)的结果的二进制中至少有一位是1。假设最后一位是1的位是第m位。那么x^ax^bx^c的结果中,有一个或者三个数字的第m位是1

接下来我们证明x^ax^bx^c的三个结果第m位不可能都是1。还是用反证法证明。如果x^ax^bx^c的第m位都是1,那么abc三个数字的第m位和x的第m位都相反,因此abc三个数字的第m位相同。如果abc三个数字的第m位都是0x=a^b^c结果的第m位是0。由于xa两个数字的第m位都是0x^a结果的第m位应该是0。同理可以证明x^bx^cm位都是0。这与我们的假设矛盾。如果abc三个数字的第m位都是1x=a^b^c结果的第m位是1。由于xa两个数字的第m位都是1x^a结果的第m位应该是0。同理可以证明x^bx^cm位都是0。这还是与我们的假设矛盾。

因此x^ax^bx^c三个数字中,只有一个数字的第m位是1。于是我们找到了能够区分abc三个数字的标准。这三个数字中,只有一个数字满足这个标准,而另外两个数字不满足。一旦这个满足标准数字找出来之后,另外两个数字也就可以找出来了。

#include <iostream>#include <vector>using namespace std;//得到输入数据的只有最后一个1的数int lastBitOf1(int number){return number & ~(number - 1);}void getTwoUnique(vector<int>::iterator begin, vector<int>::iterator end, vector<int>& unique);void getThreeUnique(vector<int>& numbers, vector<int>& unique){if(numbers.size() < 3)return;int index = 0;vector<int>::iterator iter = numbers.begin();//所有数异或过后的结果保存在index中for(; iter != numbers.end(); ++iter)index ^= *iter;//将index分别与所有的数异或得到flagint flags = 0;for(iter = numbers.begin(); iter != numbers.end(); ++iter)flags ^= lastBitOf1(index ^ *iter);flags = lastBitOf1(flags);//此时flag必然不为0,,可以通过flag推出与flag同样位置为1的那个不同的数int first = 0;for(iter = numbers.begin(); iter != numbers.end(); ++iter){if(lastBitOf1(*iter ^ index) == flags)first ^= *iter;}unique.push_back(first);for(iter = numbers.begin(); iter != numbers.end(); ++iter){if(*iter == first){swap(*iter, *(numbers.end() - 1));break;}}getTwoUnique(numbers.begin(), numbers.end() - 1, unique);}//处理只有2个数不同时void getTwoUnique(vector<int>::iterator begin, vector<int>::iterator end, vector<int>& unique){int xorResult = 0;for(vector<int>::iterator iter = begin; iter != end; ++iter)xorResult ^= *iter;int diff = lastBitOf1(xorResult);int first = 0;int second = 0;for(vector<int>::iterator iter = begin; iter != end; ++iter){if(diff & *iter)first ^= *iter;elsesecond ^= *iter;}unique.push_back(first);unique.push_back(second);}int main(){vector<int> vec1;vector<int> vec2;vec1.push_back(1);vec1.push_back(3);vec1.push_back(4);vec1.push_back(2);vec1.push_back(3);vec1.push_back(1);vec1.push_back(4);vec1.push_back(5);vec1.push_back(7);getThreeUnique(vec1,vec2);for (auto it=vec2.begin();it!=vec2.end();++it){cout<<*it<<endl;}return 0;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子咳嗽打哈切流鼻涕发烧怎么办 孩子香蕉吃多了怎么办 80多岁老人发烧怎么办 小孩香蕉吃多了怎么办 7个月宝宝缺钙怎么办 宝宝脖子被汗淹到红了脱皮怎么办? 小儿出汗多咳嗽怎么办吃什么 牛高烧不退怎么办最好 猪体温低不吃食怎么办 小孩发烧咳嗽怎么办吃什么药 大晚上发烧39度怎么办 胃受凉了老打嗝怎么办 大人发低烧怎么办如何退烧 吃了退热药不退热怎么办 猪持续高烧不退怎么办 猪感冒了不吃食怎么办 6岁儿童发烧38度怎么办 5岁儿童发烧38度怎么办 7岁儿童发烧38度怎么办 儿童发烧到38度怎么办 4岁儿童发烧38度怎么办 9岁儿童发烧38度怎么办 5儿童发烧38度怎么办 咳嗽了20多天怎么办 嘴角烂了怎么办涂什么药 感冒发烧到39度怎么办 6岁宝宝发烧头痛怎么办 生完孩子耻骨疼怎么办 顺产底下外阴红肿伤口流脓怎么办 产后便秘怎么办什么方法最有效 一周岁宝宝拉肚怎么办 三岁宝宝拉水怎么办 喝了过期的青汁怎么办 吃了黑心的苹果怎么办 新生儿两天没拉大便怎么办 贝亲奶瓶不漏怎么办 满月婴儿吃多了怎么办 婴儿吃撑了哭闹怎么办 新生儿吃撑了怎么办啊 新生儿吃了奶粉不吃奶怎么办 新生儿不吃奶也不吃奶粉怎么办