题目描述:

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路分析:

1. 直接想法,每个数字遍历,统计出现次数,复杂度O(n^2),超时。

2. 借助哈希表,空间换时间,遍历一次,时间复杂度O(n),空间复杂度O(n),对于空间复杂度限制为O(1)时,不满足条件。

3. 利用异或运算。已知两个相同的数,异或为0。若当前的题目是只求一个只出现一次的数字时,只需要将数组中的数字都异或一次,最后得到的即为所求的只出现一次的数字。那么拓展到两个数字的情况,

我们可以将原始数组分成两个子数组,使得每个子数组包含一个只出现一次的数字,而其他数字都成对出现。这样,我们就可以用上述方法找到那个孤苦伶仃的元素。

我们还是从头到尾一次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数组的异或结果。因为其他数字都出现了两次,在异或中全部抵消了。由于两个数字肯定不一样,那么异或的结果肯定不为0,也就是说这个结果数组的二进制表示至少有一个位为1。我们在结果数组中找到第一个为1的位的位置,记为第n位。现在我们以第n位是不是1为标准把元数组中的数字分成两个子数组,第一个子数组中每个数字的第n位都是1,而第二个子数组中每个数字的第n位都是0。

举例:{2,4,3,6,3,2,5,5}

我们依次对数组中的每个数字做异或运行之后,得到的结果用二进制表示是0010。异或得到结果中的倒数第二位是1,于是我们根据数字的倒数第二位是不是1分为两个子数组。第一个子数组{2,3,6,3,2}中所有数字的倒数第二位都是1,而第二个子数组{4,5,5}中所有数字的倒数第二位都是0。接下来只要分别两个子数组求异或,就能找到第一个子数组中只出现一次的数字是6,而第二个子数组中只出现一次的数字是4。

代码:

思路二:

 class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
if(data.size()<=)
return;
map<int, int> data_map;
for(int i=; i<data.size(); i++)
{
data_map[data[i]]++;
}
vector<int> v;
for(int i=; i<data.size(); i++)
{
if(data_map[data[i]]==)
v.push_back(data[i]);
}
*num1 = v[];
*num2 = v[];
}
};

思路三:

class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int length = data.size();
if(length<)
return;
//对原始数组求异或
int resultExclusiveOR = ;
for(int i=; i<length; i++)
resultExclusiveOR ^= data[i]; unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
*num1 = ;
*num2 = ;
for(int j=; j<length; j++)
{
if(IsBit1(data[j], indexOf1))
{
*num1 ^= data[j];
}
else
{
*num2 ^= data[j];
}
}
}
private:
//找到二进制数num第一个为1的位数,如0010,第一个为1的位数是2
unsigned int FindFirstBitIs1(int num)
{
unsigned int indexBit = ;
//只判断一个字节的
while((num & )== && (indexBit < *sizeof(unsigned int)))
{
num = num >> ;
indexBit++;
}
return indexBit;
}
//判断第indexBit位是否为1
bool IsBit1(int num, unsigned int indexBit)
{
num = num >> indexBit;
return (num & );
}
};

剑指offer:数组中只出现一次的数字的更多相关文章

  1. 剑指Offer 数组中只出现一次的数字

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.   思路: 因为有2个数字只出现了一次,而其他的数字都是2次,可以通过异或运算,得到最后这2个只 ...

  2. 剑指Offer——数组中只出现一次的数字

    题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 分析: 数组中一共有偶数个数.两个数字只出现过一次. 相同数异或在一起等于0,那么将所有数异或 ...

  3. 剑指Offer——数组中只出现一次的数字(一个很帅的异或解法)

    题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 看题目脑子里就出现做法了: 遍历,用个HashMap来记录出现的次数,然后再遍历HashMap返回 ...

  4. 用java刷剑指offer(数组中只出现一次的数字)

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 牛客网链接 思路 链接:https://www.nowcoder.com/questionTer ...

  5. leetcode 136. Single Number 、 137. Single Number II 、 260. Single Number III(剑指offer40 数组中只出现一次的数字)

    136. Single Number 除了一个数字,其他数字都出现了两遍. 用亦或解决,亦或的特点:1.相同的数结果为0,不同的数结果为1 2.与自己亦或为0,与0亦或为原来的数 class Solu ...

  6. 剑指Offer-40.数组中只出现一次的数字(C++/Java)

    题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 分析: 我们知道,两个相同的数字异或的结果等于0,所以利用这个性质将数组中所有的数字异或,求得的结 ...

  7. 剑指offer--35.数组中只出现一次的数字

    时间限制:1秒 空间限制:32768K 热度指数:198150 本题知识点: 数组 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. class ...

  8. 剑指 Offer —— 数组中重复的数字

    数组中的重复数字 题目描述 牛课网链接 长度为 n 的数组里,所有数字都在 0 到 n-1 的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一 ...

  9. 剑指offer 数组中重复的数

    在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为7的数组{ ...

  10. 剑指offer——数组中出现次数超过一半的数字(c++)

    题目描述数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.如 ...

随机推荐

  1. vue请求简单配置

    简单记录一下vue的http请求配置相关 测试环境请求接口设置: 1.  config/dev.env.js添加: module.exports = merge(prodEnv, { NODE_ENV ...

  2. JavaWeb 之 Listener:监听器

    一.概述 1.事件监听机制 事件:        一件事情 事件源:    事件发生的地方 监听器:    一个对象 注册监听: 将事件.事件源.监听器绑定在一起. 2.监听器概念 当事件源上发生某个 ...

  3. CentOS 7 - 以root身份登入Gnome

    新版的7.0很多资料没有,为了安全,linux是禁止root登录到桌面,但为了方便又想用root登录到桌面,在网上找了找,基本上都是这这一篇: http://shaoguangleo.blog.163 ...

  4. static 关键字有什么作用

    static关键字的含义及使用场景 static是Java50个关键字之一.static关键字可以用来修饰代码块表示静态代码块,修饰成员变量表示全局静态成员变量,修饰方法表示静态方法.(注意:不能修饰 ...

  5. 在DoNetMVC中使用控制反转和依赖注入【DI】

    本次是在MVC5中使用Autofac 第一步:程序包管理器控制台 Install-Package Autofac.MVC5 引入nuget包 这样成功之后,会在引用中出现两个DLL,分别是Autofa ...

  6. Linux安装和配置MySQL5.7【修改密码、修改字符集等配置】(5.7.18+版本也可参考,我是5.7.22)

    本文是转载篇,这里是 原文原文原文. --------------------分割线------------------------------- 这下面内容讲述如何修改密码为简单密码(比如:1234 ...

  7. Python爬虫系列:五、正则表达式

    1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. 正则表达式 ...

  8. ffmpeg音频视频转格式工具使用

    ffmpeg是音频视频编解码工具,是一个开源项目,可以改变视频格式,比如mp4格式转ogg格式(有格式工厂,多这个东西纯属自己娱乐一下) 官方网址:www.ffmpeg.org 下载后找到ffmpeg ...

  9. java集合-遍历arraylist-for循环-从指定下标开始遍历-for的用法

    转载:http://www.9191boke.com/blogdetails/681220549.html java集合的for循环遍历有多种方式,但是都是从下标0开始遍历,有时会有从中间下标开始遍历 ...

  10. gson之将对象转化成json字符串的方法

    public class GsonUtil { /** * 将object对象转成json格式字符串 */ public static String toJson(Object object) { G ...