From 95f908803dd670c2ddeb0b7ba84282440d6ce7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=A0=91=E6=A3=AE?= Date: Thu, 8 Aug 2019 14:53:52 +0800 Subject: [PATCH] Create 137. Single Number II.md --- solutions/137. Single Number II.md | 69 ++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 solutions/137. Single Number II.md diff --git a/solutions/137. Single Number II.md b/solutions/137. Single Number II.md new file mode 100644 index 0000000..1d2147b --- /dev/null +++ b/solutions/137. Single Number II.md @@ -0,0 +1,69 @@ +# [137. Single Number II](https://leetcode.com/problems/single-number-ii/) +# 思路 +这道题是 [136. Single Number](https://leetcode.com/problems/single-number/)的拓展,136的解法就是利用计算机按位储存数字的特性来做的, +这道题就是除了一个单独的数字之外,数组中其他的数字都出现了三次,由于需要线性复杂度,所以还是要利用位操作。 + +## 思路一 +我们可以建立一个32位的数字,来统计每一位上1出现的个数,我们知道如果某一位上为1的话, +那么如果该整数出现了三次,对3去余为0,我们把每个数的对应位都加起来对3取余,最终剩下来的那个数就是单独的数字。 + +## 思路二 +将思路一的计数过程也改成位操作将会更简洁。我们用整数one表示出现了1次,two表示出现了2次,当出现3次的时候清零。 +可以列出状态转换表(《数字电路》课程里面貌似叫做真值表)如下: + +|编号| input | one | two| new_one |new_two| 备注| +|--| ---| --- | -- |------ |----- | ---| +|1| 0 | 0 | 0 | 0| 0| | +|2| 0 | 0 | 1 | 0| 1| | +|3| 0 | 1 | 0 | 1| 0| | +|4| 1 | 0 | 0 | 1| 0| | +|5| 1 | 0 | 1 | 0| 0| 三个1,清零 | +|6| 1 | 1 | 0 | 0| 1| | + +注意上表中不可能出现one和two都为1的情况。根据上表我们可以写出状态表达式: +``` +根据表格第3、4行: +new_one = [(~input) & one & (~two)] | [input & (~one) & (~two)] = (input ^ one) & (~two) + +同理根据第2、6行: +new_two = [(~input) & two & (~new_one)] | [input & (~two) & (~new_one)] = (input ^ two) & (~new_one) +``` +(学过《数字电路》的同学可能更好理解上述化简过程) + + + + +# C++ +## 思路一 +``` C++ +class Solution { +public: + int singleNumber(vector& nums) { + int res = 0; + for(int i = 0; i < 32; i++){ + int count = 0; + for(int j = 0; j < nums.size(); j++){ + count += ((nums[j] >> i) & 1); + } + count %= 3; + res |= count * (1 << i); + } + return res; + } +}; +``` + +## 思路二 +``` C++ +class Solution { +public: + int singleNumber(vector& nums) { + int one = 0, two = 0; + for(auto &num: nums){ + one = (~two) & (one ^ num); + two = (~one) & (two ^ num); + } + return one; + } +}; +```