leetcode-137-Single Number II-第二种解法
题目描述:
详细的题目描述见上一篇博客《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-第二种解法的更多相关文章
- LeetCode 137. Single Number II(只出现一次的数字 II)
LeetCode 137. Single Number II(只出现一次的数字 II)
- Leetcode 137 Single Number II 仅出现一次的数字
原题地址https://leetcode.com/problems/single-number-ii/ 题目描述Given an array of integers, every element ap ...
- [LeetCode] 137. Single Number II 单独数 II
Given a non-empty array of integers, every element appears three times except for one, which appears ...
- LeetCode 137 Single Number II(仅仅出现一次的数字 II)(*)
翻译 给定一个整型数组,除了某个元素外其余的均出现了三次. 找出这个元素. 备注: 你的算法应该是线性时间复杂度. 你能够不用额外的空间来实现它吗? 原文 Given an array of inte ...
- [LeetCode] 137. Single Number II 单独的数字之二
Given a non-empty array of integers, every element appears three times except for one, which appears ...
- 详解LeetCode 137. Single Number II
Given an array of integers, every element appears three times except for one, which appears exactly ...
- leetcode 137. Single Number II ----- java
Given an array of integers, every element appears three times except for one. Find that single one. ...
- Java [Leetcode 137]Single Number II
题目描述: Given an array of integers, every element appears three times except for one. Find that single ...
- LeetCode 137 Single Number II 数组中除了一个数外,其他的数都出现了三次,找出这个只出现一次的数
Given an array of integers, every element appears three times except for one, which appears exactly ...
- Java for LeetCode 137 Single Number II
Given an array of integers, every element appears three times except for one. Find that single one. ...
随机推荐
- CloudStack 脚本封装分析
cloud.keystore是这样生成的 String dname = "cn=\"" + cn + "\",ou=\"" + o ...
- 相机IMU融合四部曲(一):D-LG-EKF详细解读
相机IMU融合四部曲(一):D-LG-EKF详细解读 极品巧克力 前言 前两篇文章<Google Cardbord的九轴融合算法>,<Madgwick算法详细解读>,讨论的都是 ...
- Window: move\copy\xcopy
Move 移动文件和重命名文件与目录. 要移动一个或多个文件: MOVE [/Y | /-Y] [drive:][path]filename1[,...] destination 要重命名目录: MO ...
- AspectJ AOP介绍
idea下aspectj程序运行示例 有些同学可能想自己编写aspect程序进行测试练习,博主在这简单介绍运行环境的搭建,首先博主使用的idea的IDE,因此只对idea进行介绍.首先通过maven仓 ...
- Metadata Service 最高频的应用 - 每天5分钟玩转 OpenStack(164)
实现 instance 定制化,cloud-init(或 cloudbase-init)只是故事的一半,metadata service 则是故事的的另一半.两者的分工是:metadata servi ...
- win10 家庭版使用注册表关闭windows defender
管理员身份运行 reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender" /v " ...
- Perl 学习笔记-输入输出
1.读取标准输入<STDIN>(行输入操作=> 读取一行直到换行符) chomp($line = <STDIN>); # 读取一行并去掉最后的换行符(不会自动去掉) pr ...
- Http面试题
http请求由三部分组成,分别是:请求行.消息报头.请求正文 HTTP(超文本传输协议)是一个基于请求与响应模式的.无状态的.应用层的协议,常基于TCP的连接方式,HTTP1.1版本中给出一种持续连接 ...
- 关于如何在服务器上搭建tomcat并发布自己的web项目
最近在学习如何在服务起上搭建tomcat,并发布自己的项目,自己是花了一下午的时间才把里面的东西弄明白,各种百度,各种请教大神,真的是备受折磨啊.好了废话不多说,直接进入主题. 1:众所周知,tomc ...
- 回归(regression)、梯度下降(gradient descent)
本文由LeftNotEasy所有,发布于http://leftnoteasy.cnblogs.com.如果转载,请注明出处,在未经作者同意下将本文用于商业用途,将追究其法律责任. 前言: 上次写过一篇 ...