详解LeetCode 137. Single Number II
Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
题意: 在一个整型数组里,只有一个数字出现一次,其他数字都出现了3次,求这个只出现一次的数字(single number)。
这真是非常非常有意思的一道题目。如果直接统计各数字出现的次数当然也能达到目的,不过空间复杂度为O(N)。能否用O(1)空间解决此问题呢?
首先注意到,对于某个二进制位,如果single number的该位为1,那么所有数字在该二进制位上1出现的总次数不能被3 整除,且余数为1。比如数组{3, 3, 3, 2},转化为二进制表示: {11, 11, 11, 10},二进制位01出现的次数为3次,二进制位10出现的次数为4次。
因此我们只需要计算出每个二进制位1出现次数除以3的余数,就可以轻松得到该single number。
模3的余数有3个: 0, 1, 2,对应二进制表示: 00, 01, 10,需要两个二进制位来表示。
我们可以用两个整数one和two来分别表示各二进制位1出现的次数模3的余数。
显然直接累加统计次数然后取模是不现实的,这时候就要用到位运算了,这也是本题解法最有技巧的一部分。
如何设计位运算模拟累加模3的结果呢?
假设当前累加到数组中的数字num,考察one,two和num在二进制位取不同值下,累加1的出现次数模3的结果:


One'和Two'分别表示累加后模3的新余数的第一位和第二位。
举例
假设当前二进制位1出现的次数模3为1,数字num在该二进制位为0,那么1的出现次数不变,模3依然为1,对应两个真值表的第二行: One' = 1, Two' = 0。
假设当前二进制位1出现的次数模3为2,数字num在该二进制位为1,那么1的出现次数+1,模3结果变为0,对应两个真值表的第四行: One' = 0, Two' = 0。
因此,以上真值表就包含了所有情况下累加模3的结果。
如何将真值表转化为位运算的逻辑表达式呢?这时候就要用到一个大杀器:卡诺图 (Karnaugh map)。
以下是两个真值表转化来的卡诺图:
One'

Two'

解释:
列头表示num在该位为0或1的情况,行头表示当前余数的值。
两张表表内的0和1分别表示给定num和余数,进行累加模3操作后,One' 和 Two'的值,大家可以对比之前的真值表体会一下。
注意余数为11的情况是不存在的,因此结果标记为x,这列其实可以删掉。之所以写出来是为了体现卡诺图的逻辑条件是按格雷码排列的,简单说就是相邻的二进制条件只有1位是不一样的。这样方便转化为逻辑表达式的时候进行化简,简单说就是卡诺图里相邻并且构成矩形的1的情况可以简化为用一个逻辑表达式来表示。具体可以参考卡诺图Wiki页面的例子。这个问题的卡诺图比较简单,不存在化简的情况。
接下来将卡诺图转换为逻辑表达式。
以One'为例。图中只有两个格子为1,也即num = 0, two = 0, one =1 和 num = 1, two = 0, one = 0的情况。因此我们有:
one = (~num & ~two & one) + (num & ~one & ~two);
只有以上两种情况之一,one可以取值1,其他情况皆为0。注意C++里位操作符&, ^, |等的优先级低于加法操作符,因此需要括号括起来。
Two的逻辑表达式可以类推。
以下为完整代码。因为single number的1只出现一次,模3余数肯定为1,因此直接返回one即可。
int singleNumber(vector<int>& nums) {
int one = , two = ;
for (int i = ; i < nums.size(); i++) {
int num = nums[i];
int newOne = (~num & ~two & one) + (num & ~one & ~two);
two = (~num & two & ~one) + (num & ~two & one);
one = newOne;
}
return one;
}
详解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 an array of inte ...
- [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 单独的数字之二
Given a non-empty array of integers, every element appears three times except for one, which appears ...
- 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. ...
随机推荐
- Window各种命令补
- codeforces 388D Fox and Perfect Sets(线性基+数位dp)
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp mak ...
- Java虚拟机10:Client模式和Server模式的区别
部分商用虚拟机中,Java程序最初是通过解释器对.class文件进行解释执行的,当虚拟机发现某个方法或代码块运行地特别频繁的时候,就会把这些代码认定为热点代码Hot Spot Code(这也是我们使用 ...
- LCTF wp简单复现
1.T4lk 1s ch34p,sh0w m3 the sh31l 代码如下: <?php $SECRET = `../read_secret`; $SANDBOX = "../dat ...
- 35、springboot-运行状态监控使用Actuator
Spring Boot Actuator 提供了运行状态监控的功能 Actuator 监控数据可以通过阻REST远程 shell 和JMX方式获得.我 首先来介绍通过 REST 方式查看 Actuat ...
- 8、Web Service-IDEA-jaxws规范下的 spring整合CXF
前提:开发和之前eclipse的开发有很大的不同! 1.服务端的实现 1.新建项目 此时创建的是web项目 2.此时创建的项目是不完整的需要开发人员手动补充完整 3.对文件夹的设置(满满的软件使用方法 ...
- 使用Apache HttpClient 4.x发送Json数据
Apache HttpClient是Apache提供的一个开源组件,使用HttpClient可以很方便地进行Http请求的调用.自4.1版本开始,HttpClient的API发生了较大的改变,很多方法 ...
- UVA - 1160(简单建模+并查集)
A secret service developed a new kind of explosive that attain its volatile property only when a spe ...
- 删除gitlab上的分支
好久没有更新了, 今天记录一下删除gitlab上的分支的操作 登录仓库后, 依次点击: project --> home --> Readme --> repository --&g ...
- Oracle索引实现方式