题目描述:

详细的题目描述见上一篇博客《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. ”$-”与shell默认选项

    一.前言 之所以整理这篇博客,主要是写Linux环境设置文件 的时候,在查看/etc/profile时看到这么一段代码: for i in /etc/profile.d/*.sh ; do if [ ...

  2. Tomcat内存溢出及大小调整

    一.在使用Java程序从数据库中查询大量的数据或是应用服务器(如tomcat.jboss,weblogic)加载jar包时会出现java.lang.OutOfMemoryError异常.这主要是由于应 ...

  3. bootstrap导入JavaScript插件

    Bootstrap的JavaScript插件可以单独导入到页面中,也可以一次性导入到页面中.因为在Bootstrap中的JavaScript插件都是依赖于jQuery库,所以不论是单独导入还一次性导入 ...

  4. PCA 原理

      PCA的数学原理(转) 1 年前 PCA(Principal Component Analysis)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取 ...

  5. 去除SVN图标并解除svn控制 (转)

    今天一不小心把F盘弄成了SVN管理项目,结果如图: 看到这个,当场晕菜,经过不懈的努力终于找到一种方法,如下: 右键  ===>TortoiseSVN   ===>Settings 点击确 ...

  6. logcat命令详解【一】

    Android日志系统提供了记录和查看系统调试信息的功能.日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来查看和使用. 在使用logcat之前,请确保手机的USB调试 ...

  7. Qt之生成pdf(转)

    Qt中如何让图片.文本.HTML或者其他形式的内容生成pdf呢?主要利用QPrinter来实现,QPrinter不止可以操作打印机来打印纸张文件,并且可以将文件保存至磁盘,存储为pdf格式的文件.   ...

  8. xampp 添加ssl 访问

    编辑php.ini 文件,找到 “;extension=php_openssl.dll” (去掉前面的;号注释) <VirtualHost *:8090> DocumentRoot &qu ...

  9. 使用word写博客

    目前大部分的博客作者在写博客这件事情上都会遇到以下3个痛点:1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.2.发布到博客或公众号平台 ...

  10. 团体程序设计天梯赛L1-022 奇偶分家 2017-03-22 17:48 81人阅读 评论(0) 收藏

    L1-022. 奇偶分家 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定N个正整数,请统计奇数和偶数各有多少个? 输入格式 ...