Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.

Note:

Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

Example 1:

Input: [2,2,3,2]
Output: 3

Example 2:

Input: [0,1,0,1,0,1,99]
Output: 99

这道题是之前那道 Single Number 的延伸,那道题的解法就比较独特,是利用计算机按位储存数字的特性来做的,这道题就是除了一个单独的数字之外,数组中其他的数字都出现了三次,还是要利用位操作 Bit Manipulation 来解。可以建立一个 32 位的数字,来统计每一位上1出现的个数,如果某一位上为1的话,那么如果该整数出现了三次,对3取余为0,这样把每个数的对应位都加起来对3取余,最终剩下来的那个数就是单独的数字。代码如下:

解法一:

class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = ;
for (int i = ; i < ; ++i) {
int sum = ;
for (int j = ; j < nums.size(); ++j) {
sum += (nums[j] >> i) & ;
}
res |= (sum % ) << i;
}
return res;
}
};

还有一种解法,思路很相似,用3个整数来表示 INT 的各位的出现次数情况,one 表示出现了1次,two 表示出现了2次。当出现3次的时候该位清零。最后答案就是one的值。

  1. ones   代表第 ith 位只出现一次的掩码变量
  2. twos  代表第 ith 位只出现两次次的掩码变量
  3. threes  代表第 ith 位只出现三次的掩码变量

假设现在有一个数字1,更新 one 的方法就是 ‘亦或’ 这个1,则 one 就变成了1,而 two 的更新方法是用上一个状态下的 one 去 ‘与’ 上数字1,然后 ‘或’ 上这个结果,这样假如之前 one 是1,那么此时 two 也会变成1,这 make sense,因为说明是当前位遇到两个1了;反之如果之前 one 是0,那么现在 two 也就是0。注意更新的顺序是先更新 two,再更新 one,不理解的话只要带个只有一个数字1的输入数组看一下就不难理解了。然后更新 three,如果此时 one 和 two 都是1了,由于先更新的 two,再更新的 one,two 为1,说明此时至少有两个数字1了,而此时 one 为1,说明了此时已经有了三个数字1,这块要仔细想清楚,因为 one 是要 ‘亦或’ 一个1的,值能为1,说明之前 one 为0,实际情况是,当第二个1来的时候,two 先更新为1,此时 one 再更新为0,下面 three 就是0了,那么 ‘与’ 上t hree 的相反数1不会改变 one 和 two 的值;那么当第三个1来的时候,two 还是1,此时 one 就更新为1了,那么 three 就更新为1了,此时就要清空 one 和 two 了,让它们 ‘与’ 上 three 的相反数0即可,最终结果将会保存在 one 中,参见代码如下:

解法二:

class Solution {
public:
int singleNumber(vector<int>& nums) {
int one = , two = , three = ;
for (int i = ; i < nums.size(); ++i) {
two |= one & nums[i];
one ^= nums[i];
three = one & two;
one &= ~three;
two &= ~three;
}
return one;
}
};

下面这种解法思路也十分巧妙,根据上面解法的思路,我们把数组中数字的每一位累加起来对3取余,剩下的结果就是那个单独数组该位上的数字,由于累加的过程都要对3取余,那么每一位上累加的过程就是 0->1->2->0,换成二进制的表示为 00->01->10->00,可以写出对应关系:

00 (+) 1 = 01

01 (+) 1 = 10

10 (+) 1 = 00 ( mod 3)

用 ab 来表示开始的状态,对于加1操作后,得到的新状态的 ab 的算法如下:

b = b xor r & ~a;

a = a xor r & ~b;

这里的 ab 就是上面的三种状态 00,01,10 的十位和各位,刚开始的时候,a和b都是0,当此时遇到数字1的时候,b更新为1,a更新为0,就是 01 的状态;再次遇到1的时候,b更新为0,a更新为1,就是 10 的状态;再次遇到1的时候,b更新为0,a更新为0,就是 00 的状态,相当于重置了;最后的结果保存在b中,明白了上面的分析过程,就能写出代码如下;

解法三:

class Solution {
public:
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;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/137

类似题目:

Single Number

Single Number III

参考资料:

https://leetcode.com/problems/single-number-ii/

https://leetcode.com/problems/single-number-ii/discuss/43294/Challenge-me-thx

https://leetcode.com/problems/single-number-ii/discuss/43296/An-General-Way-to-Handle-All-this-sort-of-questions.

https://leetcode.com/problems/single-number-ii/discuss/43297/Java-O(n)-easy-to-understand-solution-easily-extended-to-any-times-of-occurance

https://leetcode.com/problems/single-number-ii/discuss/43295/Detailed-explanation-and-generalization-of-the-bitwise-operation-method-for-single-numbers

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Single Number II 单独的数字之二的更多相关文章

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

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

  2. [LeetCode] Single Number III 单独的数字之三

    Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...

  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——Single Number II(找出数组中只出现一次的数2)

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

  5. LeetCode:Single Number II

    题目地址:here 题目大意:一个整数数组中,只有一个数出现一次,其余数都出现3次,在O(n)时间,O(1)空间内找到这个出现一次的数 对于”只有一个数出现一次,其余数出现2次“的情况,很简单,只要把 ...

  6. [leetcode]Single Number II @ Python

    原题地址:http://oj.leetcode.com/problems/single-number-ii/ 题意:Given an array of integers, every element ...

  7. [Leetcode] single number ii 找单个数

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

  8. LeetCode——Single Number II

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

  9. [LeetCode] Single Number II 位运算

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

随机推荐

  1. css3新单位学习

    vw,vh,vmin,vmax vw 1vw = 视窗width*1% vh 1vh = 视窗heihgt*1% 如果视窗的宽度小于高度,1vmin = 1vw,如果视窗宽度大于高度,1vmin = ...

  2. 高分辨率下IE浏览器缩放导致出现右侧滚动条问题的解决

    0 问题描述 由于需要演示触控操作,采购了SurfacePro,SurfacePro的推荐分辨率为2736×1824,且默认缩放比例为200%,IE浏览器的默认缩放比例也是200%,这样就导致右侧出现 ...

  3. PreEmptive Dotfuscator and Analytics CE

    PreEmptive Dotfuscator and Analytics CE Dotfuscator 是领先的 .NET 模糊处理程序和压缩程序,有助于防止程序遭到反向工程,同时使程序更小更高效.D ...

  4. 虚拟机安装CentOS6.4

    1  概述 虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统,运行在主机上,完全独立,虚拟机里面的所有操作不会影响主机,即使虚拟 ...

  5. .Net Html如何上传图片到一般应用程序

    用html实现图片上传 后台采用.net其中在这里要借用一个js插件 在这里我会写一个图片上传的一个小Demo,有不全的地方多多包容,和提议, 我把已经写好的demo已经上传到百度云 在这里可以下载 ...

  6. poj1698--最大流(Dinic)

    题目大意: 爱丽丝要拍电影,有n部电影,规定爱丽丝每天只能拍一部电影,每部电影在每个礼拜只有固定的几天可以拍电影,只可以拍前面w个礼拜,并且这部电影要拍d天,问爱丽丝能不能拍完所有的电影. 思路: 建 ...

  7. spider RPC高级特性

    多租户 spider原生支持多租户部署,spider报文头对外开放了机构号.系统号两个属性用于支持多租户场景下的路由. 多租户场景下的路由可以支持下述几种模式: n  系统号: n  系统号+服务号( ...

  8. npm更新到最新版本的方法

    打开命令行工具 npm -v 查看是否是最新版本 如果不是 运行npm i npm g 升级 打开C:\Users\用户名用户目录找到node_modules 文件夹下的npm文件夹,复制一份 打开n ...

  9. iOS - 静态库的创建与使用

    在日常项目开发中,不论是为了两个公司项目上的业务交流还是为了减少项目的编译时间,有的时候我们会把项目中的私密内容打包成静态库,或者是把项目中变动较少一部分打包成静态库以便提高编译效率,那么下面我们就来 ...

  10. android 自定义控件——(一)圆角按钮

    ----------------------------------矩形或圆角类型(源代码下有属性解释)------------------------------------------------ ...