40
40
41
41
<!-- 这里可写通用的实现逻辑 -->
42
42
43
- 统计所有数字每个位中 1 出现的次数,对于某个位,1 出现的次数一定是 3 的倍数 +1 或 0。对这个数 %3 得到的结果就是那个出现一次的数字在该位上的值。
43
+ ** 方法一:位运算**
44
+
45
+ 我们可以枚举每个二进制位 $i$,对于每个二进制位,我们统计所有数字在该二进制位上的和,如果该二进制位上的和能被 $3$ 整除,那么只出现一次的数字在该二进制位上为 $0$,否则为 $1$。
46
+
47
+ 时间复杂度 $O(n \times \log M)$,空间复杂度 $O(1)$。其中 $n$ 和 $M$ 分别是数组的长度和数组中元素的范围。
48
+
49
+ ** 方法二:数字电路**
50
+
51
+ 我们考虑一种更高效的方法,该方法使用数字电路来模拟上述的位运算。
52
+
53
+ 一个整数的每个二进制位是 $0$ 或 $1$,只能表示 $2$ 种状态。但我们需要表示当前遍历过的所有整数的第 $i$ 位之和模 $3$ 的结果,因此,我们可以使用 $a$ 和 $b$ 两个整数来表示。那么会有以下三种情况:
54
+
55
+ 1 . 整数 $a$ 的第 $i$ 位为 $0$ 且整数 $b$ 的第 $i$ 位为 $0$,表示模 $3$ 结果是 $0$;
56
+ 1 . 整数 $a$ 的第 $i$ 位为 $0$ 且整数 $b$ 的第 $i$ 位为 $1$,表示模 $3$ 结果是 $1$;
57
+ 1 . 整数 $a$ 的第 $i$ 位为 $1$ 且整数 $b$ 的第 $i$ 位为 $0$,表示模 $3$ 结果是 $2$。
58
+
59
+ 我们用整数 $c$ 表示当前要读入的数,那么有以下真值表:
60
+
61
+ | $a_i$ | $b_i$ | $c_i$ | 新的 $a_i$ | 新的 $b_i$ |
62
+ | ----- | ----- | ----- | ---------- | ---------- |
63
+ | 0 | 0 | 0 | 0 | 0 |
64
+ | 0 | 0 | 1 | 0 | 1 |
65
+ | 0 | 1 | 0 | 0 | 1 |
66
+ | 0 | 1 | 1 | 1 | 0 |
67
+ | 1 | 0 | 0 | 1 | 0 |
68
+ | 1 | 0 | 1 | 0 | 0 |
69
+
70
+ 基于以上真值表,我们可以写出逻辑表达式:
71
+
72
+ $$
73
+ a_i = a_i' b_i c_i + a_i b_i' c_i'
74
+ $$
75
+
76
+ 以及:
77
+
78
+ $$
79
+ b_i = a_i' b_i' c_i + a_i' b_i c_i' = a_i' (b_i \oplus c_i)
80
+ $$
81
+
82
+ 最后结果是 $b$,因为 $b$ 的二进制位上为 $1$ 时表示这个数字出现了 $1$ 次。
83
+
84
+ 时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 是数组的长度。
44
85
45
86
<!-- tabs:start -->
46
87
@@ -62,6 +103,17 @@ class Solution:
62
103
return ans
63
104
```
64
105
106
+ ``` python
107
+ class Solution :
108
+ def singleNumber (self , nums : List[int ]) -> int :
109
+ a = b = 0
110
+ for c in nums:
111
+ aa = (~ a & b & c) | (a & ~ b & ~ c)
112
+ bb = ~ a & (b ^ c)
113
+ a, b = aa, bb
114
+ return b
115
+ ```
116
+
65
117
### ** Java**
66
118
67
119
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -83,6 +135,21 @@ class Solution {
83
135
}
84
136
```
85
137
138
+ ``` java
139
+ class Solution {
140
+ public int singleNumber (int [] nums ) {
141
+ int a = 0 , b = 0 ;
142
+ for (int c : nums) {
143
+ int aa = (~ a & b & c) | (a & ~ b & ~ c);
144
+ int bb = ~ a & (b ^ c);
145
+ a = aa;
146
+ b = bb;
147
+ }
148
+ return b;
149
+ }
150
+ }
151
+ ```
152
+
86
153
### ** Go**
87
154
88
155
需要注意 Golang 中的 ` int ` 在 64 位平台上相当于 ` int64 `
@@ -102,6 +169,18 @@ func singleNumber(nums []int) int {
102
169
}
103
170
```
104
171
172
+ ``` go
173
+ func singleNumber (nums []int ) int {
174
+ a , b := 0 , 0
175
+ for _ , c := range nums {
176
+ aa := (^a & b & c) | (a & ^b & ^c)
177
+ bb := ^a & (b ^ c)
178
+ a, b = aa, bb
179
+ }
180
+ return b
181
+ }
182
+ ```
183
+
105
184
### ** C++**
106
185
107
186
``` cpp
@@ -122,6 +201,22 @@ public:
122
201
};
123
202
```
124
203
204
+ ```cpp
205
+ class Solution {
206
+ public:
207
+ int singleNumber(vector<int>& nums) {
208
+ int a = 0, b = 0;
209
+ for (int c : nums) {
210
+ int aa = (~a & b & c) | (a & ~b & ~c);
211
+ int bb = ~a & (b ^ c);
212
+ a = aa;
213
+ b = bb;
214
+ }
215
+ return b;
216
+ }
217
+ };
218
+ ```
219
+
125
220
### ** TypeScript**
126
221
127
222
``` ts
@@ -135,6 +230,20 @@ function singleNumber(nums: number[]): number {
135
230
}
136
231
```
137
232
233
+ ``` ts
234
+ function singleNumber(nums : number []): number {
235
+ let a = 0 ;
236
+ let b = 0 ;
237
+ for (const c of nums ) {
238
+ const aa = (~ a & b & c ) | (a & ~ b & ~ c );
239
+ const bb = ~ a & (b ^ c );
240
+ a = aa ;
241
+ b = bb ;
242
+ }
243
+ return b ;
244
+ }
245
+ ```
246
+
138
247
### ** Rust**
139
248
140
249
``` rust
0 commit comments