Skip to content

Commit ef23e14

Browse files
committed
feat: add solutions to lc problem: No.0137
No.0137.Single Number II
1 parent b3509a4 commit ef23e14

File tree

7 files changed

+213
-43
lines changed

7 files changed

+213
-43
lines changed

solution/0100-0199/0137.Single Number II/README.md

+110-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,48 @@
4040

4141
<!-- 这里可写通用的实现逻辑 -->
4242

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$ 是数组的长度。
4485

4586
<!-- tabs:start -->
4687

@@ -62,6 +103,17 @@ class Solution:
62103
return ans
63104
```
64105

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+
65117
### **Java**
66118

67119
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -83,6 +135,21 @@ class Solution {
83135
}
84136
```
85137

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+
86153
### **Go**
87154

88155
需要注意 Golang 中的 `int` 在 64 位平台上相当于 `int64`
@@ -102,6 +169,18 @@ func singleNumber(nums []int) int {
102169
}
103170
```
104171

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+
105184
### **C++**
106185

107186
```cpp
@@ -122,6 +201,22 @@ public:
122201
};
123202
```
124203
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+
125220
### **TypeScript**
126221

127222
```ts
@@ -135,6 +230,20 @@ function singleNumber(nums: number[]): number {
135230
}
136231
```
137232

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+
138247
### **Rust**
139248

140249
```rust

solution/0100-0199/0137.Single Number II/README_EN.md

+68
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ class Solution:
4545
return ans
4646
```
4747

48+
```python
49+
class Solution:
50+
def singleNumber(self, nums: List[int]) -> int:
51+
a = b = 0
52+
for c in nums:
53+
aa = (~a & b & c) | (a & ~b & ~c)
54+
bb = ~a & (b ^ c)
55+
a, b = aa, bb
56+
return b
57+
```
58+
4859
### **Java**
4960

5061
```java
@@ -64,6 +75,21 @@ class Solution {
6475
}
6576
```
6677

78+
```java
79+
class Solution {
80+
public int singleNumber(int[] nums) {
81+
int a = 0, b = 0;
82+
for (int c : nums) {
83+
int aa = (~a & b & c) | (a & ~b & ~c);
84+
int bb = ~a & (b ^ c);
85+
a = aa;
86+
b = bb;
87+
}
88+
return b;
89+
}
90+
}
91+
```
92+
6793
### **Go**
6894

6995
```go
@@ -81,6 +107,18 @@ func singleNumber(nums []int) int {
81107
}
82108
```
83109

110+
```go
111+
func singleNumber(nums []int) int {
112+
a, b := 0, 0
113+
for _, c := range nums {
114+
aa := (^a & b & c) | (a & ^b & ^c)
115+
bb := ^a & (b ^ c)
116+
a, b = aa, bb
117+
}
118+
return b
119+
}
120+
```
121+
84122
### **C++**
85123

86124
```cpp
@@ -101,6 +139,22 @@ public:
101139
};
102140
```
103141
142+
```cpp
143+
class Solution {
144+
public:
145+
int singleNumber(vector<int>& nums) {
146+
int a = 0, b = 0;
147+
for (int c : nums) {
148+
int aa = (~a & b & c) | (a & ~b & ~c);
149+
int bb = ~a & (b ^ c);
150+
a = aa;
151+
b = bb;
152+
}
153+
return b;
154+
}
155+
};
156+
```
157+
104158
### **TypeScript**
105159

106160
```ts
@@ -114,6 +168,20 @@ function singleNumber(nums: number[]): number {
114168
}
115169
```
116170

171+
```ts
172+
function singleNumber(nums: number[]): number {
173+
let a = 0;
174+
let b = 0;
175+
for (const c of nums) {
176+
const aa = (~a & b & c) | (a & ~b & ~c);
177+
const bb = ~a & (b ^ c);
178+
a = aa;
179+
b = bb;
180+
}
181+
return b;
182+
}
183+
```
184+
117185
### **Rust**
118186

119187
```rust
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
class Solution {
22
public:
33
int singleNumber(vector<int>& nums) {
4-
int ans = 0;
5-
for (int i = 0; i < 32; ++i) {
6-
int cnt = 0;
7-
for (int num : nums) {
8-
cnt += ((num >> i) & 1);
9-
}
10-
cnt %= 3;
11-
ans |= cnt << i;
4+
int a = 0, b = 0;
5+
for (int c : nums) {
6+
int aa = (~a & b & c) | (a & ~b & ~c);
7+
int bb = ~a & (b ^ c);
8+
a = aa;
9+
b = bb;
1210
}
13-
return ans;
11+
return b;
1412
}
1513
};
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
func singleNumber(nums []int) int {
2-
ans := int32(0)
3-
for i := 0; i < 32; i++ {
4-
cnt := int32(0)
5-
for _, num := range nums {
6-
cnt += int32(num) >> i & 1
7-
}
8-
cnt %= 3
9-
ans |= cnt << i
2+
a, b := 0, 0
3+
for _, c := range nums {
4+
aa := (^a & b & c) | (a & ^b & ^c)
5+
bb := ^a & (b ^ c)
6+
a, b = aa, bb
107
}
11-
return int(ans)
8+
return b
129
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
class Solution {
22
public int singleNumber(int[] nums) {
3-
int ans = 0;
4-
for (int i = 0; i < 32; i++) {
5-
int cnt = 0;
6-
for (int num : nums) {
7-
cnt += num >> i & 1;
8-
}
9-
cnt %= 3;
10-
ans |= cnt << i;
3+
int a = 0, b = 0;
4+
for (int c : nums) {
5+
int aa = (~a & b & c) | (a & ~b & ~c);
6+
int bb = ~a & (b ^ c);
7+
a = aa;
8+
b = bb;
119
}
12-
return ans;
10+
return b;
1311
}
14-
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
class Solution:
22
def singleNumber(self, nums: List[int]) -> int:
3-
ans = 0
4-
for i in range(32):
5-
cnt = sum(num >> i & 1 for num in nums)
6-
if cnt % 3:
7-
if i == 31:
8-
ans -= 1 << i
9-
else:
10-
ans |= 1 << i
11-
return ans
3+
a = b = 0
4+
for c in nums:
5+
aa = (~a & b & c) | (a & ~b & ~c)
6+
bb = ~a & (b ^ c)
7+
a, b = aa, bb
8+
return b
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
function singleNumber(nums: number[]): number {
2-
let ans = 0;
3-
for (let i = 0; i < 32; i++) {
4-
const count = nums.reduce((r, v) => r + ((v >> i) & 1), 0);
5-
ans |= count % 3 << i;
2+
let a = 0;
3+
let b = 0;
4+
for (const c of nums) {
5+
const aa = (~a & b & c) | (a & ~b & ~c);
6+
const bb = ~a & (b ^ c);
7+
a = aa;
8+
b = bb;
69
}
7-
return ans;
10+
return b;
811
}

0 commit comments

Comments
 (0)