题目描述:

详细的题目描述见上一篇博客《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. Boost::lexical_cast类型转换

    1.字符串->数值 C++代码 #include <boost/lexical_cast.hpp> #include <iostream> int main() { us ...

  2. bootstrap缩略图及警示框制作

    缩略图在网站中最常用的地方就是产品列表页面,一行显示几张图片,有的在图片底下(左侧或右侧)带有标题.描述等信息.Bootstrap框架将这一部独立成一个模块组件.并通过“thumbnail”样式配合b ...

  3. Http面试题

    http请求由三部分组成,分别是:请求行.消息报头.请求正文 HTTP(超文本传输协议)是一个基于请求与响应模式的.无状态的.应用层的协议,常基于TCP的连接方式,HTTP1.1版本中给出一种持续连接 ...

  4. (转)Linux下安装Android的adb驱动-解决不能识别的问题(国产板子)

    注:本文不涉及怎么安装adb等工具.本方法通用.到目前为止已经解决rk3188和展讯SC6820(波导T9500)的识别问题. 以前调试的Android板子,都是直接用的Google的usb设备id, ...

  5. Promise实现简易AMD加载器

    在最新的Chrome和FF中已经 实现了Promise.有了Promise我们用数行代码即可实现一个简易AMD模式的加载器 var registry = { promises: { }, resolv ...

  6. JavaScript学习总结——转

    JavaScript学习总结(一)——JavaScript基础 JavaScript学习总结(二)——逻辑Not运算符详解 JavaScript学习总结(三)——逻辑And运算符详解 JavaScri ...

  7. 团体程序设计天梯赛L1-023 输出GPLT 2017-03-22 17:56 39人阅读 评论(0) 收藏

    L1-023. 输出GPLT 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一个长度不超过10000的.仅由英文字母构成的 ...

  8. 【小梅哥SOPC学习笔记】SOPC开发常见问题及解决办法集锦

    SOPC开发常见问题及解决办法集锦 一.Symbol 'NULL' could not be resolved 近期在评估使用NIOS II处理器进行项目的开发,我使用的软件是Quartus II 1 ...

  9. 在 Linux 系统上快速获取命令的帮助信息

    几种方法: help 命令 man 命令 info 命令 命令 --help man 章节分类如下 1 - commands 2 - system calls 3 - library calls 4 ...

  10. spring事务以及springweb

    什么是事务.事务特性.事务隔离级别.spring事务传播特性 https://www.cnblogs.com/zhangqian1031/p/6542037.html Spring AOP 中@Poi ...