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] 137. Single Number II 单独的数字之二的更多相关文章

  1. [LeetCode] 137. Single Number II 单独数 II

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

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

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

  3. LeetCode 137. Single Number II(只出现一次的数字 II)

    LeetCode 137. Single Number II(只出现一次的数字 II)

  4. Leetcode 137 Single Number II 仅出现一次的数字

    原题地址https://leetcode.com/problems/single-number-ii/ 题目描述Given an array of integers, every element ap ...

  5. LeetCode 137 Single Number II(仅仅出现一次的数字 II)(*)

    翻译 给定一个整型数组,除了某个元素外其余的均出现了三次. 找出这个元素. 备注: 你的算法应该是线性时间复杂度. 你能够不用额外的空间来实现它吗? 原文 Given an array of inte ...

  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. Leetcode#137 Single Number II

    原题地址 遍历所有数字,统计每一位出现的次数,模3即为只出现一次的数字在那一位的情况. 代码: int singleNumber(int A[], int n) { ] = {}; ; i < ...

  9. Java [Leetcode 137]Single Number II

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

随机推荐

  1. find命令常用场景

    1.查找/var目录下属主为root并且属组为mail的所有文件: find /var -user root -group mail 2.查找/usr目录下不属于root,bin,或student的文 ...

  2. Leetcode练习题Two Sum

    1 Two Sum: Question Solution 知识点总结 常见方法 HashMap由value获得key Question: Given an array of integers, ret ...

  3. Kubernetes 远程工具连接k8s集群

    Kubernetes 远程工具连接k8s集群 1.将Master的kubectl文件复制到Node内 scp k8s/kubernetes/server/bin/kubectl root@192.16 ...

  4. ASP.NET Core Web 项目文件

    在本节中,我们将探索并了解 asp.net core 项目文件. 我们使用 C#作为编程语言,因此项目文件具有.csproj 扩展名. 如果您使用过以前版本的 ASP.NET,那么您可能对此文件非常熟 ...

  5. C# Random

    一.简介 在Random类用于创建随机数.(当然是伪随机的.) 二.Random用法 例: Random rnd = new Random(); int month = rnd.Next(1, 13) ...

  6. VMware与 Device/Credential Guard 不兼容,解决办法及心得

    以下为心路历程,想要直接解决可以直接拉到最后看后续 百度要你取消Hyper-V功能,但我要用docker,以及一些相关的帖子都无效的情况下 https://blog.csdn.net/u0136677 ...

  7. 我脑中的JVM大全附带Java8的特性

    Java虚拟机-sun classic vm 世界上第一款商用的Java虚拟机. 只能使用纯解释器的方式来执行Java代码. Java虚拟机-ExactVM Exact Memory Manageme ...

  8. 前端vue项目js中怎么保证链式调用后台接口

    在一个for循环中对同一接口调用多次,如何保证逐步执行,同步执行. html部分 <DcFileUpload v-for="(item, index) of fileLengthLis ...

  9. Android自定义圆角矩形进度条2

    效果图: 或 方法讲解: (1)invalidate()方法 invalidate()是用来刷新View的,必须是在UI线程中进行工作.比如在修改某个view的显示时, 调用invalidate()才 ...

  10. JavaScript中this究竟指向什么?

    摘要: 神奇的this! 原文:JS 中 this 在各个场景下的指向 译者:前端小智 Fundebug经授权转载,版权归原作者所有. 1. this 的奥秘 很多时候, JS 中的 this 对于咱 ...