#LeetCode 137. 只出现一次的数字 II
题目链接
我的博客园地址(搬家过去了):https://www.cnblogs.com/jiangxiewei/p/12979996.html
这题起初根本想不到.直到翻了leetcode.com的discuss…然后我整个人都"awesome!!!"地瞎叫了.
下面讲讲我学来的思路.
这题本质上来讲,就是让我们做一个有限状态机(finite state machine)(瞎翻的).
首先
: 一般看到这种题,我们第一反应是做状态记录,比如数字x出现了y次.然后从记录里查询出现了一次的数字.但是现在我们的空间复杂度被限制成了O(1),不可能对所有的64位二进制表示的整数进行统计次数.
-
于是
- 我们只能着眼于二进制上了,我们先将状态记录缩小到记录目标数字的每一个 二进制上.那么这题就会变成遍历所有数,一个二进制位出现 1的次数对 3取余是否为 1,若为 1,那么我们目标数字的这一位也就是 1. 比如
- [1,1,1,2] 他们转换成二进制就是[01,01,01,10],我们可以知道第一位(从右往左)的二进制总共出现了三次1,那么我们的目标结果在第一位就绝对不会是1,相对的第二位出现了一次1,那么我们的目标值在这一位就是1 实际上
- 这题我们也可以写64个变量(不知道数据量范围多大或者32位也可以?)记录每位的二进制1出现的次数,然后每一个对三取余最后得出的64个1与0再组成一个整数…不过思路本质离不开这里 最后
- 我们要运用逻辑门的想法设计一个计数器.计数到3就回归0.对于每一个 二进制位,出现了多少次1我们可以用两个二进制表示(因为这题只需要记录%3),00表示出现0次,01表示出现1此,10表示出现2次.这样就记录了三个状态,(题目中是出现三次,其实对于x次,我们也可以同理描述).如下 补充
- 建议此题可以补充一下 逻辑代数相关知识,暂时不知道有什么好的文章,这里贴个百度百科.学习成本不高
a为高位,b为低位.两个一起表示一个两位二进制表示的数字(一个计数器)
计数器代表值 | a | b | 目标出现次数 |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 1 | 1 |
2 | 1 | 0 | 2 |
0 | 0 | 0 | 3 |
1 | 0 | 1 | 4 |
2 | 1 | 0 | 5 |
… | … | … | … |
上面是我们计数器需要达成的目标,一个计数循环.学过数字电路的同学看到这里应该就知道怎么做了.
我们再进一步. 我们遍历数据,每来一个数据c(这里一个二进制)我们的a与b就要开始为c计数,那么有以下情况
a | b |
---|