【leetcode】137.Single number II
原题链接:https://leetcode-cn.com/problems/single-number-ii/
①异或运算(XOR)

可以这么理解:xor是一个半加器,即做不进位的加法。
应用举例:交换a,b的值,一般会这么写:
int tmp=a;
a=b;
b=tmp;
而当初wzh告诉我还可以这么写:
a=a^b; b=a^b; a=a^b;
惊为天人了。
②回到这道题。最不济感觉应该也可以用用空间换时间的方式,即打一个int数组,开到数据范围那么大,然后统计出现次数就行了。但是数据范围过大。由于之前对异或的了解,也知道要用异或来做,但是只会类似136题。
于是查找资料,发现了一堆“有限状态自动机”“哈希表”之类听不懂的名词。
首先弄懂的方法:
将数写成二进制的形式,然后位运算统计每一位出现的次数。
例如:对于数据10,10,6,10,二进制为1010,1010,0110,1010
我们开个数组统计各位出现1的次数。最高位到最低位出现1的次数分别为3,1,4,0
我们将它模3,得到0,1,1,0,就是我们要求的数了,原理非常简单。但是时间复杂度较高。
class Solution { public: int singleNumber(vector<int>& nums) {int bittime[32]={0}; for(int i=0;i<nums.size();i++){ for(int j=0;j<32;j++){ if(nums[i]&(1<<j))bittime[j]++; } } int res=0; for(int i=0;i<32;i++){ res|=(bittime[i]%3)<<i; } return res; } };
③好的,现在来刚一下位运算:
再见,刚不出来,占坑,等我学了数电再来填坑。
时隔一年我回来填坑了,数电期末也是爆炸只有90.但是这不妨碍我学会了这一方法!现在我就来整理一下思路。
参考:https://www.cnblogs.com/bjwu/p/9323808.html 以及leetcode题解
首先,前面的分析也提到了二进制位统计1的方法,那么这题实际上是每一位上的1的个数模3,也就是说这题完全可以用数电里的mealy型状态机来做,这应该就是所谓FSM,有限状态机吧。
按照传统的解数电题的思路,我们列出状态转移图:

由于使用了3种状态所以使用2个二进制位进行编码:
| 当前状态 | 输入 | 下一状态与输出 |
| 00 | 0 | 00/0 |
| 00 | 1 | 01/1 |
| 01 | 0 | 01/1 |
| 01 | 1 | 10/0 |
| 10 | 0 | 10/0 |
| 10 | 1 | 00/0 |
| 11 | 无关状态 | |
| 11 | 无关状态 |
然后是卡诺图:

于是,Q1n+1=X'Q1+XQ0 , Y=Q0n+1=X'Q0+Q1'Q0'X
快乐写代码:
class Solution { public: int q1 = 0; int tmp = 0; int q0 = 0; int singleNumber(vector<int>& nums) { for(int i=0; i<nums.size(); i++){ tmp = q1; q1 = (~nums[i]&tmp) | (nums[i]&q0); q0 = (~nums[i]&q0) | (~tmp&~q0&nums[i]); } return q0; } };
顺利通过
但是这里用了一个额外变量tmp,而最优秀的答案是这样的:
class Solution: def singleNumber(self, nums: List[int]) -> int: seen_once = seen_twice = 0 for num in nums: # first appearance: # add num to seen_once # don't add to seen_twice because of presence in seen_once # second appearance: # remove num from seen_once # add num to seen_twice # third appearance: # don't add to seen_once because of presence in seen_twice # remove num from seen_twice seen_once = ~seen_twice & (seen_once ^ num) seen_twice = ~seen_once & (seen_twice ^ num) return seen_once
刚看到时我的心情和热门评论一样:

仔细分析其实挺有道理的,但是我想不到这么高级的方法。
就这样吧。

浙公网安备 33010602011771号