原题网址:http://www.lintcode.com/zh-cn/problem/single-number-iii/#

给出2*n + 2个的数字,除其中两个数字之外其他每个数字均出现两次,找到这两个数字。

您在真实的面试中是否遇到过这个题?

Yes
样例

给出 [1,2,2,3,4,4,5,3],返回 1和5

挑战

O(n)时间复杂度,O(1)的额外空间复杂度

标签

 
思路:
最开始用暴力循环来破解,设置一个与数组长度相同的vector<bool>,二重循环遍历数组找到不重复的两个数,标记为false,再遍历vector<bool>将对应不重复元素压入结果数组中,运行时显示超时……我就知道没这么简单。
 
改进算法:嗯,主要是减少时间复杂度。联想到前几个例子,可以利用起来,首先用sort排序,然后一次遍历找到第一个落单的数,将其压入结果数组中;
                 再将第一个落单的数再次压入输入数组中,这样形参数组A中就只剩一个落单的数了,接下来用异或找到第二个落单的数压入结果数组中,最后AC。
 class Solution {
public:
/*
* @param A: An integer array
* @return: An integer array
*/
vector<int> singleNumberIII(vector<int> &A) {
// write your code here
vector<int> result;
if (A.empty())
{
return result;
}
int size=A.size();
sort(A.begin(),A.end());
for (int i=;i<size-;i+=)
{
if (A[i]-A[i+]!=)
{
result.push_back(A[i]);
A.push_back(A[i]);
break;
}
}
int temp=;
for (int j=;j<(int)A.size();j++)
{
temp=temp^A[j];
}
result.push_back(temp);
return result;
}
};

挑战版: 参考 https://blog.csdn.net/guoziqing506/article/details/52231357

我们之前已经做过两道类似的题目,分别是落单的数落单的数 II,思路都是位运算。这道题也不例外。

不过这道题想出方法来倒还真不太容易,至少我当时没想出来,也是后来查了别人的做法,才知道的,在此,我将别人的方法用我的话再说一遍,努力让它更好理解。

当然,首先想到的就是跟之前2*n + 1个数时的情况一样(详见:落单的数),先将所有的数异或一遍,这样,我们就将数组中那两个不同的数异或到了一个结果中(此处不懂的话看刚才给的链接)。现在的难处在于无法将这个结果拆开,拆成我们想要的那两个不同的数。

怎么办呢?我们如果对二进制足够熟悉,就不难得出这样一个结论,这个异或的结果(为方便描述,记为Xor)的二进制位中为1的位,必然是这两个不同的数(方便起见,记为first 和 second)不同的位,也就是说,first和second在这些位中一个是1,一个是0。不失一般性,我们就找Xor中第一个为1的位,将这个位数记为k.

那么,一定隐含了这样一个逻辑:在成对的2*n个数当中,一定有2x个数的第k位是1,而有2y个数的第k位是0,其中,x + y = n,所以,

换个说法,既然Xor的第k为是1,那我们不妨假设first的第k位是0,而second的第k位是1。那么,如果令x个数第k位为1的数,和second一起,与Xor异或,就能得到first,这个道理与2n + 1时是一样的。而再令first与Xor异或,就能得到second.

于是,可以按以下步骤操作:

1. 将数组中所有的数异或,得到一个结果,记为Xor

2. 查出Xor中第一个为1的位(也就是为1的最小的位),记为k

3. 查出数组中所有第k位为1的数(这里面当然包括second)与Xor异或,得到first

4. 将first与Xor异或,得到second

PS:位运算不会改变原变量的值。要改变原变量的值需要经过赋值表达式实现。

vector<int> singleNumberIII(vector<int> &A)
{
vector<int> result;
int temp=;
for (int i=;i<(int)A.size();i++)
{
temp=temp^A[i];
}
int first=temp;
int second=temp; int k=;
for (;k<;k++)
{
if(temp>>k&)
break;
} for (int j=;j<(int)A.size();j++)
{
if (A[j]>>k&)
{
first=first^A[j];
}
}
second=second^first; //second=temp^first;
result.push_back(first);
result.push_back(second);
return result;
}

其他参考:

https://blog.csdn.net/wangyuquanliuli/article/details/46638551

https://www.cnblogs.com/libaoquan/p/7141364.html

84 落单的数 III的更多相关文章

  1. lintcode 中等题:Single number III 落单的数III

    题目 落单的数 III 给出2*n + 2个的数字,除其中两个数字之外其他每个数字均出现两次,找到这两个数字. 样例 给出 [1,2,2,3,4,4,5,3],返回 1和5 挑战 O(n)时间复杂度, ...

  2. lintcode 落单的数(位操作)

    题目1 落单的数 给出2*n + 1 个的数字,除其中一个数字之外其他每个数字均出现两次,找到这个数字. 链接:http://www.lintcode.com/zh-cn/problem/single ...

  3. lintcode-84-落单的数 III

    84-落单的数 III 给出2*n + 2个的数字,除其中两个数字之外其他每个数字均出现两次,找到这两个数字. 样例 给出 [1,2,2,3,4,4,5,3],返回 1和5 挑战 O(n)时间复杂度, ...

  4. lintcode 中等题:Singleton number II 落单的数 II

    题目 落单的数 II 给出3*n + 1 个的数字,除其中一个数字之外其他每个数字均出现三次,找到这个数字. 样例 给出 [1,1,2,3,3,3,2,2,4,1] ,返回 4 挑战 一次遍历,常数级 ...

  5. lintcode:落单的数

    题目: 落单的数 给出2*n + 1 个的数字,除其中一个数字之外其他每个数字均出现两次,找到这个数字. 样例 给出 [1,2,2,1,3,4,3],返回 4 挑战 一次遍历,常数级的额外空间复杂度 ...

  6. [codevs3295]落单的数

    题目描述 Description 有n个数(n是奇数),其中n-1个数两两成对,有1个数落单,找出这个数.要求O(n)的时间复杂度,O(1)的空间复杂度 输入描述 Input Description ...

  7. LeetCode 136. Single Number (落单的数)

    Given an array of integers, every element appears twice except for one. Find that single one. Note:Y ...

  8. LinCode落单的数

    easy 落单的数 查看执行结果 60% 通过 给出2*n + 1 个的数字,除当中一个数字之外其它每一个数字均出现两次.找到这个数字. 您在真实的面试中是否遇到过这个题? Yes 例子 给出 [1, ...

  9. 83 落单的数 II

    原题网址:http://www.lintcode.com/zh-cn/problem/single-number-ii/ 给出3*n + 1 个的数字,除其中一个数字之外其他每个数字均出现三次,找到这 ...

随机推荐

  1. 19-MySQL-Ubuntu-数据表的查询-自关联(八)

    自关联   转自:https://blog.csdn.net/hubingzhong/article/details/81277220

  2. HDU 3966 /// 树链剖分+树状数组

    题意: http://acm.hdu.edu.cn/showproblem.php?pid=3966 给一棵树,并给定各个点权的值,然后有3种操作: I x y z : 把x到y的路径上的所有点权值加 ...

  3. 【csp】2017-12

    第一题:游戏 题目: 题意:啊,不多赘述.看的懂. 题解:sort一下直接暴力比较大小. 代码: #include<iostream> #include<cstdio> #in ...

  4. 【转】Java程序CPU飙升问题排查方法

    windows环境下cpu飙升问题 线上某台runtime机器(windows Server)cpu报警,这种情况初步就是代码里面死循环了,先把机器下线了保证不再有新的任务分配进来,然而cpu使用依然 ...

  5. ionic js 加载动画 ionSpinner 提供了许多种旋转加载的动画图标。当你的界面加载时,你就可以呈现给用户相应的加载图标。 该图标采用的是SVG

    ionic 加载动画 ion-spinner ionSpinner 提供了许多种旋转加载的动画图标.当你的界面加载时,你就可以呈现给用户相应的加载图标. 该图标采用的是SVG. 用法 <ion- ...

  6. javascript 的学习笔记(第一天)

    1.==与=== ==   先转换类型,再比较 ===  直接比较 2.parseInt  把字符串转成整数 parsefloat  把字符串转成小数 3. 变量的作用域:变量起作用的范围 局部变量: ...

  7. ibator配置文件说明文档

    1. <classPathEntry>  属性名 说明 示例 location 数据库驱动文件路径 lib/mysql-connector-java-5.1.6-bin.jar   2.  ...

  8. MySQL 知识点随记

    1.存储过程中声明变量要在程序的最前面,也要在声明事务开始的前,不然会报错 2.Mysql 获取32位guid: REPLACE(UUID(),"-","") ...

  9. 正则表达式 判断内容是否为合法的url

    var strUrl= "^((https|http|ftp|rtsp|mms)?://)" + "?(([0-9a-z_!~*'().&=+$%-]+: )?[ ...

  10. Linux和Windows下ping命令详解

    转:http://linux.chinaitlab.com/command/829332.html 一.Linux下的ping参数 用途 发送一个回送信号请求给网络主机. 语法 ping [ -d] ...