Skip to content

Commit 41c173b

Browse files
committedJan 5, 2023
feat: add solutions to lc problem: No.1803
No.1803.Count Pairs With XOR in a Range
1 parent 45228f2 commit 41c173b

File tree

6 files changed

+22
-82
lines changed

6 files changed

+22
-82
lines changed
 

‎solution/1800-1899/1803.Count Pairs With XOR in a Range/README.md

+12-32
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,20 @@
6161

6262
另外,对于数组异或计数问题,我们通常可以使用“0-1 字典树”来解决。
6363

64-
在字典树中,我们定义两个函数,一个是 $insert(x)$,表示将数 $x$ 插入到字典树中;另一个是 $search(x, limit)$,表示在字典树中查找与 $x$ 异或值小于 $limit$ 的数对数量。
64+
字典树的节点定义如下:
6565

66-
对于 $insert(x)$ 函数,我们将数字 $x$ 按照二进制位从高到低的顺序,插入到“0-1 字典树”中,其中字典树的每个节点表示一个二进制位,每个节点有两个子节点,表示 $0$ 和 $1$。如果当前二进制位为 $0$,则插入到左子节点,否则插入到右子节点。然后将当前节点的计数值 $cnt$ 加 $1$。
66+
- `children[0]``children[1]` 分别表示当前节点的左右子节点;
67+
- `cnt` 表示以当前节点为结尾的数的数量。
6768

68-
对于 $search(x, limit)$ 函数,我们从字典树的根节点 `node` 开始,遍历 $x$ 的二进制位,从高到低,记当前 $x$ 的二进制位的数为 $v$。
69+
在字典树中,我们还定义了以下两个函数:
6970

70-
- 如果当前 $limit$ 的二进制位为 $1$,此时我们可以直接将答案加上与 $x$ 的当前二进制位 $v$ 相同的子节点的计数值 $cnt$,然后将当前节点移动到与 $x$ 的当前二进制位 $v$ 不同的子节点,即 `node = node.children[v ^ 1]`。继续遍历下一位。
71-
- 如果当前 $limit$ 的二进制位为 $0$,此时我们只能将当前节点移动到与 $x$ 的当前二进制位 $v$ 相同的子节点,即 `node = node.children[v]`。继续遍历下一位。
71+
其中一个函数是 $insert(x)$,表示将数 $x$ 插入到字典树中。该函数将数字 $x$ 按照二进制位从高到低的顺序,插入到“0-1 字典树”中。如果当前二进制位为 $0$,则插入到左子节点,否则插入到右子节点。然后将节点的计数值 $cnt$ 加 $1$。
7272

73-
遍历完 $x$ 的二进制位后,返回答案。
73+
另一个函数是 $search(x, limit)$,表示在字典树中查找与 $x$ 异或值小于 $limit$ 的数量。该函数从字典树的根节点 `node` 开始,遍历 $x$ 的二进制位,从高到低,记当前 $x$ 的二进制位的数为 $v$。如果当前 $limit$ 的二进制位为 $1$,此时我们可以直接将答案加上与 $x$ 的当前二进制位 $v$ 相同的子节点的计数值 $cnt$,然后将当前节点移动到与 $x$ 的当前二进制位 $v$ 不同的子节点,即 `node = node.children[v ^ 1]`。继续遍历下一位。如果当前 $limit$ 的二进制位为 $0$,此时我们只能将当前节点移动到与 $x$ 的当前二进制位 $v$ 相同的子节点,即 `node = node.children[v]`。继续遍历下一位。遍历完 $x$ 的二进制位后,返回答案。
7474

7575
有了以上两个函数,我们就可以解决本题了。
7676

77-
我们遍历数组 `nums`,对于每个数 $x$,我们先在字典树中查找与 $x$ 异或值小于 $high+1$ 的数对数量,然后在字典树中查找与 $x$ 异或值小于 $low$ 的数对数量,将两者的差值加到答案中。然后将 $x$ 插入到字典树中。继续遍历下一个数 $x$,直到遍历完数组 `nums`。最后返回答案即可。
77+
我们遍历数组 `nums`,对于每个数 $x$,我们先在字典树中查找与 $x$ 异或值小于 $high+1$ 的数量,然后在字典树中查找与 $x$ 异或值小于 $low$ 的数对数量,将两者的差值加到答案中。接着将 $x$ 插入到字典树中。继续遍历下一个数 $x$,直到遍历完数组 `nums`。最后返回答案即可。
7878

7979
时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n \times \log M)$。其中 $n$ 为数组 `nums` 的长度,而 $M$ 为数组 `nums` 中的最大值。本题中我们直接取 $\log M = 16$。
8080

@@ -103,16 +103,14 @@ class Trie:
103103
node = self
104104
ans = 0
105105
for i in range(15, -1, -1):
106+
if node is None:
107+
return ans
106108
v = x >> i & 1
107109
if limit >> i & 1:
108110
if node.children[v]:
109111
ans += node.children[v].cnt
110-
if node.children[v ^ 1] is None:
111-
return ans
112112
node = node.children[v ^ 1]
113113
else:
114-
if node.children[v] is None:
115-
return ans
116114
node = node.children[v]
117115
return ans
118116

@@ -151,20 +149,14 @@ class Trie {
151149
public int search(int x, int limit) {
152150
Trie node = this;
153151
int ans = 0;
154-
for (int i = 15; i >= 0; --i) {
152+
for (int i = 15; i >= 0 && node != null; --i) {
155153
int v = (x >> i) & 1;
156154
if (((limit >> i) & 1) == 1) {
157155
if (node.children[v] != null) {
158156
ans += node.children[v].cnt;
159157
}
160-
if (node.children[v ^ 1] == null) {
161-
return ans;
162-
}
163158
node = node.children[v ^ 1];
164159
} else {
165-
if (node.children[v] == null) {
166-
return ans;
167-
}
168160
node = node.children[v];
169161
}
170162
}
@@ -207,20 +199,14 @@ public:
207199
int search(int x, int limit) {
208200
Trie* node = this;
209201
int ans = 0;
210-
for (int i = 15; ~i; --i) {
202+
for (int i = 15; ~i && node; --i) {
211203
int v = x >> i & 1;
212204
if (limit >> i & 1) {
213205
if (node->children[v]) {
214206
ans += node->children[v]->cnt;
215207
}
216-
if (!node->children[v ^ 1]) {
217-
return ans;
218-
}
219208
node = node->children[v ^ 1];
220209
} else {
221-
if (!node->children[v]) {
222-
return ans;
223-
}
224210
node = node->children[v];
225211
}
226212
}
@@ -272,20 +258,14 @@ func (this *Trie) insert(x int) {
272258
273259
func (this *Trie) search(x, limit int) (ans int) {
274260
node := this
275-
for i := 15; i >= 0; i-- {
261+
for i := 15; i >= 0 && node != nil; i-- {
276262
v := (x >> i) & 1
277263
if (limit >> i & 1) == 1 {
278264
if node.children[v] != nil {
279265
ans += node.children[v].cnt
280266
}
281-
if node.children[v^1] == nil {
282-
return
283-
}
284267
node = node.children[v^1]
285268
} else {
286-
if node.children[v] == nil {
287-
return
288-
}
289269
node = node.children[v]
290270
}
291271
}

‎solution/1800-1899/1803.Count Pairs With XOR in a Range/README_EN.md

+5-25
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,14 @@ class Trie:
9595
node = self
9696
ans = 0
9797
for i in range(15, -1, -1):
98+
if node is None:
99+
return ans
98100
v = x >> i & 1
99101
if limit >> i & 1:
100102
if node.children[v]:
101103
ans += node.children[v].cnt
102-
if node.children[v ^ 1] is None:
103-
return ans
104104
node = node.children[v ^ 1]
105105
else:
106-
if node.children[v] is None:
107-
return ans
108106
node = node.children[v]
109107
return ans
110108

@@ -141,20 +139,14 @@ class Trie {
141139
public int search(int x, int limit) {
142140
Trie node = this;
143141
int ans = 0;
144-
for (int i = 15; i >= 0; --i) {
142+
for (int i = 15; i >= 0 && node != null; --i) {
145143
int v = (x >> i) & 1;
146144
if (((limit >> i) & 1) == 1) {
147145
if (node.children[v] != null) {
148146
ans += node.children[v].cnt;
149147
}
150-
if (node.children[v ^ 1] == null) {
151-
return ans;
152-
}
153148
node = node.children[v ^ 1];
154149
} else {
155-
if (node.children[v] == null) {
156-
return ans;
157-
}
158150
node = node.children[v];
159151
}
160152
}
@@ -197,20 +189,14 @@ public:
197189
int search(int x, int limit) {
198190
Trie* node = this;
199191
int ans = 0;
200-
for (int i = 15; ~i; --i) {
192+
for (int i = 15; ~i && node; --i) {
201193
int v = x >> i & 1;
202194
if (limit >> i & 1) {
203195
if (node->children[v]) {
204196
ans += node->children[v]->cnt;
205197
}
206-
if (!node->children[v ^ 1]) {
207-
return ans;
208-
}
209198
node = node->children[v ^ 1];
210199
} else {
211-
if (!node->children[v]) {
212-
return ans;
213-
}
214200
node = node->children[v];
215201
}
216202
}
@@ -262,20 +248,14 @@ func (this *Trie) insert(x int) {
262248
263249
func (this *Trie) search(x, limit int) (ans int) {
264250
node := this
265-
for i := 15; i >= 0; i-- {
251+
for i := 15; i >= 0 && node != nil; i-- {
266252
v := (x >> i) & 1
267253
if (limit >> i & 1) == 1 {
268254
if node.children[v] != nil {
269255
ans += node.children[v].cnt
270256
}
271-
if node.children[v^1] == nil {
272-
return
273-
}
274257
node = node.children[v^1]
275258
} else {
276-
if node.children[v] == nil {
277-
return
278-
}
279259
node = node.children[v]
280260
}
281261
}

‎solution/1800-1899/1803.Count Pairs With XOR in a Range/Solution.cpp

+1-7
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,14 @@ class Trie {
1717
int search(int x, int limit) {
1818
Trie* node = this;
1919
int ans = 0;
20-
for (int i = 15; ~i; --i) {
20+
for (int i = 15; ~i && node; --i) {
2121
int v = x >> i & 1;
2222
if (limit >> i & 1) {
2323
if (node->children[v]) {
2424
ans += node->children[v]->cnt;
2525
}
26-
if (!node->children[v ^ 1]) {
27-
return ans;
28-
}
2926
node = node->children[v ^ 1];
3027
} else {
31-
if (!node->children[v]) {
32-
return ans;
33-
}
3428
node = node->children[v];
3529
}
3630
}

‎solution/1800-1899/1803.Count Pairs With XOR in a Range/Solution.go

+1-7
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,14 @@ func (this *Trie) insert(x int) {
2121

2222
func (this *Trie) search(x, limit int) (ans int) {
2323
node := this
24-
for i := 15; i >= 0; i-- {
24+
for i := 15; i >= 0 && node != nil; i-- {
2525
v := (x >> i) & 1
2626
if (limit >> i & 1) == 1 {
2727
if node.children[v] != nil {
2828
ans += node.children[v].cnt
2929
}
30-
if node.children[v^1] == nil {
31-
return
32-
}
3330
node = node.children[v^1]
3431
} else {
35-
if node.children[v] == nil {
36-
return
37-
}
3832
node = node.children[v]
3933
}
4034
}

‎solution/1800-1899/1803.Count Pairs With XOR in a Range/Solution.java

+1-7
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,14 @@ public void insert(int x) {
1717
public int search(int x, int limit) {
1818
Trie node = this;
1919
int ans = 0;
20-
for (int i = 15; i >= 0; --i) {
20+
for (int i = 15; i >= 0 && node != null; --i) {
2121
int v = (x >> i) & 1;
2222
if (((limit >> i) & 1) == 1) {
2323
if (node.children[v] != null) {
2424
ans += node.children[v].cnt;
2525
}
26-
if (node.children[v ^ 1] == null) {
27-
return ans;
28-
}
2926
node = node.children[v ^ 1];
3027
} else {
31-
if (node.children[v] == null) {
32-
return ans;
33-
}
3428
node = node.children[v];
3529
}
3630
}

‎solution/1800-1899/1803.Count Pairs With XOR in a Range/Solution.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,14 @@ def search(self, x, limit):
1616
node = self
1717
ans = 0
1818
for i in range(15, -1, -1):
19+
if node is None:
20+
return ans
1921
v = x >> i & 1
2022
if limit >> i & 1:
2123
if node.children[v]:
2224
ans += node.children[v].cnt
23-
if node.children[v ^ 1] is None:
24-
return ans
2525
node = node.children[v ^ 1]
2626
else:
27-
if node.children[v] is None:
28-
return ans
2927
node = node.children[v]
3028
return ans
3129

0 commit comments

Comments
 (0)
Please sign in to comment.