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. NORDIC超低功耗蓝牙4.0 NRF51822QFAA和NRF51802QFAA

    51822-QFAA和51802-QFAA在FLASH RAM的容量没有差别, 两者都是出自NORDIC原厂,: 区别在于: 1.接收灵敏度 51802是-91dBm;51822是-93dBm,这个差 ...

  2. Kubernetes容器集群管理环境 - 完整部署(下篇)

    在前一篇文章中详细介绍了Kubernetes容器集群管理环境 - 完整部署(中篇),这里继续记录下Kubernetes集群插件等部署过程: 十一.Kubernetes集群插件 插件是Kubernete ...

  3. Appium swipe实现屏幕滑动

    在 Appium 中提供 swipe() 方法来模拟用户滑动屏幕. swipe() 实现过程 是先通过在屏幕上标记两个坐标,然后再从开始坐标移动到结束坐标. 先看下 swipe 方法定义: def s ...

  4. Python之np.random.permutation()函数的使用

    官网的解释是:Randomly permute a sequence, or return a permuted range. 即随机排列序列,或返回随机范围.我的理解就是返回一个乱序的序列.下面通过 ...

  5. docker安装和配置Grafana

    目录 安装 docker 启动 配置 配置域名和端口 配置ldap 配置邮箱 添加数据源 创建dashboard 配置alert 安装 docker 启动 先普通启动,然后把配置文件导出来,修改配置文 ...

  6. 镭神激光雷达对于Autoware的适配

    1. 前言 我们的自动驾驶采用镭神激光雷达,在使用Autoware的时候,需要对镭神激光雷达的底层驱动,进行一些改变以适配Autoware. 2. 修改 (1)首先修改lslidar_c32.laun ...

  7. 超详细国外VPS搭建教程

    vps文章请访问我的github:https://github.com/pig6/vps

  8. 关于Idea突然无法输入的诡异问题解决

    问题描述 最近加班把自己的装有Debian的笔记本带到公司,使用Idea写代码的时候,突然间无法输入,ctrl与tab还可用,重启Idea能得到一阵的解决 解决参考 如果是Linux平台,请考虑是否是 ...

  9. JVM的监控工具之jstack

    参考博客:https://www.jianshu.com/p/213710fb9e40 jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threa ...

  10. Gitlab的CI/CD初尝试

    初衷:今天公司的前端和测试人员吵起来了.原因是测试埋怨前端人员把Bug的状态更改为已解决,结果代码根本没提交,而前端人员埋怨测试测的太频繁了,需要打几个环境的包不方便.又要改东西又要频繁打包费时间.凡 ...