Skip to content

Commit 932cc5a

Browse files
committed
feat: add solutions to lcci problem: No.17.19
No.17.19.Missing Two
1 parent 32903c6 commit 932cc5a

File tree

6 files changed

+239
-144
lines changed

6 files changed

+239
-144
lines changed

lcci/17.19.Missing Two/README.md

Lines changed: 92 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,19 @@
2929

3030
<!-- 这里可写通用的实现逻辑 -->
3131

32-
异或运算。与[面试题 56 - I. 数组中数字出现的次数](/lcof/面试题56%20-%20I.%20数组中数字出现的次数/README.md) 类似。
32+
**方法一:位运算**
33+
34+
利用位运算的性质:
35+
36+
1. 对于任何数 $x$,都有 $x \oplus x = 0$
37+
1. 异或运算满足结合律,即 $(a \oplus b) \oplus c = a \oplus (b \oplus c)$
38+
1. lowbit 运算获取最低一位的 $1$ 及其后面的所有 $0$,公式为 $lowbit(x) = x \& (-x)$
39+
40+
我们将 nums 中所有数进行异或到 $x$,再将 $[1,2..n]$ 的所有数也异或到 $x$。得到的 $x$ 是两个缺失的正整数的异或和。
41+
42+
然后我们运用 lowbit 获取最低一位的 $1$,那么这两个缺失的正整数在这一位上必然一个为 $1$,一个为 $0$。我们据此进行分组异或。最终得到两个缺失的正整数 $a$ 和 $b$。
43+
44+
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组长度。
3345

3446
<!-- tabs:start -->
3547

@@ -40,31 +52,22 @@
4052
```python
4153
class Solution:
4254
def missingTwo(self, nums: List[int]) -> List[int]:
43-
res, n = 0, len(nums)
44-
for i in range(n):
45-
res ^= nums[i]
46-
res ^= i + 1
47-
res ^= n + 1
48-
res ^= n + 2
49-
pos = 0
50-
while (res & 1) == 0:
51-
pos += 1
52-
res >>= 1
53-
54-
a = b = 0
55-
for num in nums:
56-
t = num >> pos
57-
if (t & 1) == 0:
58-
a ^= num
59-
else:
60-
b ^= num
61-
62-
for i in range(1, n + 3):
63-
t = i >> pos
64-
if (t & 1) == 0:
55+
n = len(nums) + 2
56+
xor = 0
57+
for v in nums:
58+
xor ^= v
59+
for i in range(1, n + 1):
60+
xor ^= i
61+
62+
diff = xor & (-xor)
63+
a = 0
64+
for v in nums:
65+
if v & diff:
66+
a ^= v
67+
for i in range(1, n + 1):
68+
if i & diff:
6569
a ^= i
66-
else:
67-
b ^= i
70+
b = xor ^ a
6871
return [a, b]
6972
```
7073

@@ -75,42 +78,82 @@ class Solution:
7578
```java
7679
class Solution {
7780
public int[] missingTwo(int[] nums) {
78-
int res = 0, n = nums.length;
79-
for (int i = 0; i < n; ++i) {
80-
res ^= nums[i];
81-
res ^= (i + 1);
81+
int n = nums.length + 2;
82+
int xor = 0;
83+
for (int v : nums) {
84+
xor ^= v;
8285
}
83-
res ^= (n + 1);
84-
res ^= (n + 2);
85-
86-
int pos = 0;
87-
while ((res & 1) == 0) {
88-
pos += 1;
89-
res >>= 1;
86+
for (int i = 1; i <= n; ++i) {
87+
xor ^= i;
9088
}
91-
92-
int a = 0, b = 0;
93-
for (int num : nums) {
94-
int t = num >> pos;
95-
if ((t & 1) == 0) {
96-
a ^= num;
97-
} else {
98-
b ^= num;
89+
int diff = xor & (-xor);
90+
int a = 0;
91+
for (int v : nums) {
92+
if ((v & diff) != 0) {
93+
a ^= v;
9994
}
10095
}
101-
for (int i = 1; i <= n + 2; ++i) {
102-
int t = i >> pos;
103-
if ((t & 1) == 0) {
96+
for (int i = 1; i <= n; ++i) {
97+
if ((i & diff) != 0) {
10498
a ^= i;
105-
} else {
106-
b ^= i;
10799
}
108100
}
101+
int b = xor ^ a;
109102
return new int[] {a, b};
110103
}
111104
}
112105
```
113106

107+
### **C++**
108+
109+
```cpp
110+
class Solution {
111+
public:
112+
vector<int> missingTwo(vector<int>& nums) {
113+
int n = nums.size() + 2;
114+
int eor = 0;
115+
for (int v : nums) eor ^= v;
116+
for (int i = 1; i <= n; ++i) eor ^= i;
117+
118+
int diff = eor & -eor;
119+
int a = 0;
120+
for (int v : nums) if (v & diff) a ^= v;
121+
for (int i = 1; i <= n; ++i) if (i & diff) a ^= i;
122+
int b = eor ^ a;
123+
return {a, b};
124+
}
125+
};
126+
```
127+
128+
### **Go**
129+
130+
```go
131+
func missingTwo(nums []int) []int {
132+
n := len(nums) + 2
133+
xor := 0
134+
for _, v := range nums {
135+
xor ^= v
136+
}
137+
for i := 1; i <= n; i++ {
138+
xor ^= i
139+
}
140+
diff := xor & -xor
141+
a := 0
142+
for _, v := range nums {
143+
if (v & diff) != 0 {
144+
a ^= v
145+
}
146+
}
147+
for i := 1; i <= n; i++ {
148+
if (i & diff) != 0 {
149+
a ^= i
150+
}
151+
}
152+
b := xor ^ a
153+
return []int{a, b}
154+
}
155+
```
156+
114157
### **...**
115158

116159
```

lcci/17.19.Missing Two/README_EN.md

Lines changed: 79 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -39,31 +39,22 @@
3939
```python
4040
class Solution:
4141
def missingTwo(self, nums: List[int]) -> List[int]:
42-
res, n = 0, len(nums)
43-
for i in range(n):
44-
res ^= nums[i]
45-
res ^= i + 1
46-
res ^= n + 1
47-
res ^= n + 2
48-
pos = 0
49-
while (res & 1) == 0:
50-
pos += 1
51-
res >>= 1
52-
53-
a = b = 0
54-
for num in nums:
55-
t = num >> pos
56-
if (t & 1) == 0:
57-
a ^= num
58-
else:
59-
b ^= num
60-
61-
for i in range(1, n + 3):
62-
t = i >> pos
63-
if (t & 1) == 0:
42+
n = len(nums) + 2
43+
xor = 0
44+
for v in nums:
45+
xor ^= v
46+
for i in range(1, n + 1):
47+
xor ^= i
48+
49+
diff = xor & (-xor)
50+
a = 0
51+
for v in nums:
52+
if v & diff:
53+
a ^= v
54+
for i in range(1, n + 1):
55+
if i & diff:
6456
a ^= i
65-
else:
66-
b ^= i
57+
b = xor ^ a
6758
return [a, b]
6859
```
6960

@@ -72,42 +63,82 @@ class Solution:
7263
```java
7364
class Solution {
7465
public int[] missingTwo(int[] nums) {
75-
int res = 0, n = nums.length;
76-
for (int i = 0; i < n; ++i) {
77-
res ^= nums[i];
78-
res ^= (i + 1);
66+
int n = nums.length + 2;
67+
int xor = 0;
68+
for (int v : nums) {
69+
xor ^= v;
7970
}
80-
res ^= (n + 1);
81-
res ^= (n + 2);
82-
83-
int pos = 0;
84-
while ((res & 1) == 0) {
85-
pos += 1;
86-
res >>= 1;
71+
for (int i = 1; i <= n; ++i) {
72+
xor ^= i;
8773
}
88-
89-
int a = 0, b = 0;
90-
for (int num : nums) {
91-
int t = num >> pos;
92-
if ((t & 1) == 0) {
93-
a ^= num;
94-
} else {
95-
b ^= num;
74+
int diff = xor & (-xor);
75+
int a = 0;
76+
for (int v : nums) {
77+
if ((v & diff) != 0) {
78+
a ^= v;
9679
}
9780
}
98-
for (int i = 1; i <= n + 2; ++i) {
99-
int t = i >> pos;
100-
if ((t & 1) == 0) {
81+
for (int i = 1; i <= n; ++i) {
82+
if ((i & diff) != 0) {
10183
a ^= i;
102-
} else {
103-
b ^= i;
10484
}
10585
}
86+
int b = xor ^ a;
10687
return new int[] {a, b};
10788
}
10889
}
10990
```
11091

92+
### **C++**
93+
94+
```cpp
95+
class Solution {
96+
public:
97+
vector<int> missingTwo(vector<int>& nums) {
98+
int n = nums.size() + 2;
99+
int eor = 0;
100+
for (int v : nums) eor ^= v;
101+
for (int i = 1; i <= n; ++i) eor ^= i;
102+
103+
int diff = eor & -eor;
104+
int a = 0;
105+
for (int v : nums) if (v & diff) a ^= v;
106+
for (int i = 1; i <= n; ++i) if (i & diff) a ^= i;
107+
int b = eor ^ a;
108+
return {a, b};
109+
}
110+
};
111+
```
112+
113+
### **Go**
114+
115+
```go
116+
func missingTwo(nums []int) []int {
117+
n := len(nums) + 2
118+
xor := 0
119+
for _, v := range nums {
120+
xor ^= v
121+
}
122+
for i := 1; i <= n; i++ {
123+
xor ^= i
124+
}
125+
diff := xor & -xor
126+
a := 0
127+
for _, v := range nums {
128+
if (v & diff) != 0 {
129+
a ^= v
130+
}
131+
}
132+
for i := 1; i <= n; i++ {
133+
if (i & diff) != 0 {
134+
a ^= i
135+
}
136+
}
137+
b := xor ^ a
138+
return []int{a, b}
139+
}
140+
```
141+
111142
### **...**
112143

113144
```

lcci/17.19.Missing Two/Solution.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Solution {
2+
public:
3+
vector<int> missingTwo(vector<int>& nums) {
4+
int n = nums.size() + 2;
5+
int eor = 0;
6+
for (int v : nums) eor ^= v;
7+
for (int i = 1; i <= n; ++i) eor ^= i;
8+
9+
int diff = eor & -eor;
10+
int a = 0;
11+
for (int v : nums) if (v & diff) a ^= v;
12+
for (int i = 1; i <= n; ++i) if (i & diff) a ^= i;
13+
int b = eor ^ a;
14+
return {a, b};
15+
}
16+
};

lcci/17.19.Missing Two/Solution.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
func missingTwo(nums []int) []int {
2+
n := len(nums) + 2
3+
xor := 0
4+
for _, v := range nums {
5+
xor ^= v
6+
}
7+
for i := 1; i <= n; i++ {
8+
xor ^= i
9+
}
10+
diff := xor & -xor
11+
a := 0
12+
for _, v := range nums {
13+
if (v & diff) != 0 {
14+
a ^= v
15+
}
16+
}
17+
for i := 1; i <= n; i++ {
18+
if (i & diff) != 0 {
19+
a ^= i
20+
}
21+
}
22+
b := xor ^ a
23+
return []int{a, b}
24+
}

0 commit comments

Comments
 (0)