题目描述:

详细的题目描述见上一篇博客《leetcode-137-Single Number II-第一种解法》,这里简单说一下。

有一个数组,所有元素都出现了三次,除了一个元素只出现了一次。输出这个只出现一次的元素。

要求时间复杂度O(n),空间复杂度O(1)。

要完成的函数:

int singleNumber(vector<int>& s)

说明:

上一篇博客中提出的方法很容易理解,但是不是O(n)的时间复杂度,而是O(n^2),这点应该很多朋友都能看出来。

今天给大家分享一个O(n)的方法,先贴出简洁的代码给大家欣赏一下。这个方法同样参考于discuss区。

代码:

int singleNumber(vector<int>& nums)
{
int a = , b = ;
for (int i = ; i < nums.size(); ++i)
{
b = (b ^ nums[i]) & ~a;
a = (a ^ nums[i]) & ~b;
}
return b;
}

短短几行代码,简洁扼要地完成了任务。以下举例详细说明为什么能这样子做,以及推测要如何产生这样子的想法。

举例说明:

数组为[2,2,2,3],一共有四个元素,进行四次循环。

第一次循环,b=(0000^0010)&1111=0010=2,a=(0000^0010)&1101=0000=0

第二次循环,b=(0010^0010)&1111=0000=0,a=(0000^0010)&1111=0010=2

第三次循环,b=(0000^0010)&1101=0000=0,a=(0010^0010)&1111=0000=0

第四次循环,b=(0000^0011)&1111=0011=3,a=(0000^0011)&1100=0000=0

不知道大家有没有发现,某个值nums[i]第一次出现的时候,b把它记录了下来,这时候a=0;接着第二次出现的时候,b被清空了,记录到了a里面;接着第三次出现的时候,b和a都被清空了。

如果一个数组中,所有的元素除了一个特殊的只出现一次,其他都出现了三次,那么根据我们刚刚观察到的结论,最后这个特殊元素必定会被记录在b中。

有些朋友会说,但是不一定数组都是刚好3个2都在一起,3个4都在一起,都能够满足刚刚这样子的做法。

上上篇博客136题中,笔者本人提出了异或其实是满足交换律和结合律的,而且&这个操作也是满足交换律和结合律的,所以无论3个2会不会一起出现,结果都是会刚好抵消的。

所以上述的方法可以解决这个问题。

怎么想出这种方法的:

其实discuss区的大神是设计了一种方法,借由这种方法推出了a和b的变换方式…

我们想要达到的效果其实是——

            a  b

初始状态      :   0   0

第一次碰见某个数x:   0   x(把x记录在b中)

第二次碰见某个数x:   x   0(把x记录在a中)

第三次碰见某个数x:   0   0(把a和b都清空,可以处理其他数)

还记得我们之前处理“所有元素都出现两次,只有一个特殊元素出现一次”的问题吗?其实我们那会想要达到的状态也是——

            a

初始状态      :   0

第一次碰见某个数x:   x(把x记录在a中)

第二次碰见某个数x:   0(把a清空)

然后我们刚好就找到了异或运算可以处理这个问题。

那么这次我们同样利用异或运算,看能不能设计出一种变换的方法让a和b按照上述变换规则,进行转换。

b=0时碰到x,就变成x;b=x时再碰到x,就变成0,这个不就是异或吗?所以我们也许可以设计b=b xor x。

但是当b=0时再再碰到x,这时候b还是要为0,但这时候不同的是a=x,而前两种情况都是a=0。所以我们可以设计成:b=(b xor x)&~a

同样道理,我们可以设计出:a=(a xor x)&~b

在这种变换规则下,a和b都能按照我们设定的状态来发生转化。最后那个只出现一次的元素必定存储在b中。

感想:

异或真的是个神奇的东西,它其实已经内含了“判断”的过程。想一下我们“所有元素都出现两次,只有一个特殊元素出现一次”的问题,我们如果设计一个int型整数result用来记录,假定数组为[2,3,4,2,3],我们当然可以不断地result+2+3+4,但是到了第二次出现2的时候,要怎么判断这个2已经出现过了,这时候要result-2呢?但是异或就可以,只要你出现过一次,它就会永久记得你。

话说异或是怎么实现的?我记得好像跟二进制加法有关?

leetcode-137-Single Number II-第二种解法的更多相关文章

  1. LeetCode 137. Single Number II(只出现一次的数字 II)

    LeetCode 137. Single Number II(只出现一次的数字 II)

  2. Leetcode 137 Single Number II 仅出现一次的数字

    原题地址https://leetcode.com/problems/single-number-ii/ 题目描述Given an array of integers, every element ap ...

  3. [LeetCode] 137. Single Number II 单独数 II

    Given a non-empty array of integers, every element appears three times except for one, which appears ...

  4. LeetCode 137 Single Number II(仅仅出现一次的数字 II)(*)

    翻译 给定一个整型数组,除了某个元素外其余的均出现了三次. 找出这个元素. 备注: 你的算法应该是线性时间复杂度. 你能够不用额外的空间来实现它吗? 原文 Given an array of inte ...

  5. [LeetCode] 137. Single Number II 单独的数字之二

    Given a non-empty array of integers, every element appears three times except for one, which appears ...

  6. 详解LeetCode 137. Single Number II

    Given an array of integers, every element appears three times except for one, which appears exactly ...

  7. leetcode 137. Single Number II ----- java

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  8. Java [Leetcode 137]Single Number II

    题目描述: Given an array of integers, every element appears three times except for one. Find that single ...

  9. LeetCode 137 Single Number II 数组中除了一个数外,其他的数都出现了三次,找出这个只出现一次的数

    Given an array of integers, every element appears three times except for one, which appears exactly ...

  10. Java for LeetCode 137 Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one. ...

随机推荐

  1. 191. Number of 1 Bits 二进制中1的个数

    [抄题]: Write a function that takes an unsigned integer and returns the number of ’1' bits it has (als ...

  2. RPM简介与基本使用

    一.什么是RPM RPM的全名是Red Hat Package Manager,本意是Red Hat 软件包管理,顾名思义是Red Hat 贡献出来的软件包管理:在Fedora .Redhat.Man ...

  3. 第一个Django应用程序_part2

    一.数据库配置 此文延续第一个Django应用程序_part1. 打开mystic/settings.py.这是一个普通的Python模块,其模块变量表示Django配置 默认情况下,配置使用SQLi ...

  4. loadrunner怎样进行手动关联

    转自:http://novasblog.blog.163.com/blog/static/43713514200901341934981/ 手动关联的主要步骤为:        第一步:录制测试脚本, ...

  5. [C++] STACK_Principle

    STACK_Principle

  6. Linux下查看Nginx的并发连接数和连接状态-乾颐堂

    Linux下查看Nginx等的并发连接数和连接状态. 1.查看Web服务器(Nginx Apache)的并发请求数及其TCP连接状态: netstat -n | awk '/^tcp/ {++S[$N ...

  7. jquery UI datepicker汉化

    由于近期工作需要,jquery ui的datepicker需要汉化,特此把代码贴在这$(function() { $.datepicker.regional["zh-CN"] = ...

  8. CRISPR/Cas9基因敲除原理及实验建议

    CRISPR/Cas9基因敲除原理及实验建议   CRISPR Cas9已经成为了最受欢迎的基因编辑技术之一,在2016年的国自然基金中也有很多项目是关于 CRISPR Cas9的.目前在市场上已经有 ...

  9. 如何写摘要(abstract)

  10. mysql 数学操作函数

    -- 绝对值,圆周率 SELECT ABS(-1),3*PI() -- 平方根,求余 SELECT SQRT(9),MOD(9,5) -- 获取整数的函数 SELECT CEIL(12.145),CE ...