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. 用SignalR 2.0开发客服系统[系列5:使用SignalR的中文简体语言包和其他技术点]

    前言 交流群:195866844 目录: 用SignalR 2.0开发客服系统[系列1:实现群发通讯] 用SignalR 2.0开发客服系统[系列2:实现聊天室] 用SignalR 2.0开发客服系统 ...

  2. 分享在winform下实现模块化插件编程-优化版

    上一篇<分享在winform下实现模块化插件编程>已经实现了模块化编程,但我认为不够完美,存在以下几个问题: 1.IAppContext中的CreatePlugInForm方法只能依据完整 ...

  3. ViEmu 3.6.0 过期 解除30天限制的方法

    下载:链接: http://pan.baidu.com/s/1c2HUuWw 密码: sak8 删除下面2个地方 HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{B9CDA4 ...

  4. C#开发微信门户及应用(37)--微信公众号标签管理功能

    微信公众号,仿照企业号的思路,增加了标签管理的功能,对关注的粉丝可以设置标签管理,实现更加方便的分组管理功能.开发者可以使用用户标签管理的相关接口,实现对公众号的标签进行创建.查询.修改.删除等操作, ...

  5. java环境搭建和写出一个Helloworld

    一.安装环境和配置环境变量(必要环节) 安装java并配置环境变量 :在"系统变量"中设置3项属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),若已存在则点击 ...

  6. 关于xml加载提示: Error on line 1 of document : 前言中不允许有内容

    我是在java中做的相关测试, 首先粘贴下报错: 读取xml配置文件:xmls\property.xml org.dom4j.DocumentException: Error on line 1 of ...

  7. mysql 安装

    编译环境yum install gcc gcc-c++ ncurses-devel perl 依赖yum install boost boost-devel boost-doc 安装cmake wge ...

  8. entityframework学习笔记--008-实体数据建模基础之继承关系映射TPH

    Table per Hierarchy Inheritance 建模 1.让我们假设你有如图8-1中的表,Employee表包含hourly employees 和salaried employees ...

  9. HTML DOM总结

    MDN的定义 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口.它给文档(结构树)提供了一个结构化的表述并且定义了一种方式—程序可以对结构树进行访问,以改变文档的结构,样式和内容. ...

  10. CSS布局 -- 圣杯布局 & 双飞翼布局

    按照我的理解,其实圣杯布局跟双飞翼布局的实现,目的都是左右两栏固定宽度,中间部分自适应. 但在这里实现起来还是有一些区别的 [圣杯布局] 在这里,实现了左(200px) 右(220px) 宽度固定,中 ...