Skip to content

Commit 33881af

Browse files
committed
feat: update solutions to lc/lcof2 problems
* lc No.0421 & lcof2 No.067. Maximum XOR of Two Numbers in an Array
1 parent 7b14fde commit 33881af

File tree

7 files changed

+459
-765
lines changed

7 files changed

+459
-765
lines changed

lcof2/剑指 Offer II 067. 最大的异或/README.md

+120-192
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,15 @@
6868

6969
<!-- 这里可写通用的实现逻辑 -->
7070

71-
哈希表或前缀树实现。
71+
**方法一:哈希表**
72+
73+
**方法二:前缀树**
74+
75+
题目是求两个元素的异或最大值,可以从最高位开始考虑。
76+
77+
我们把数组中的每个元素 $x$ 看作一个 $32$ 位的 $01$ 串,按二进制从高位到低位的顺序,插入前缀树(最低位为叶子节点)。
78+
79+
搜索 $x$ 时,尽量走相反的 $01$ 字符指针的策略,因为异或运算的法则是相同得 $0$,不同得 $1$,所以我们尽可能往与 $x$ 当前位相反的字符方向走,才能得到能和 $x$ 产生最大值的结果。
7280

7381
<!-- tabs:start -->
7482

@@ -101,53 +109,35 @@ class Solution:
101109
```python
102110
class Trie:
103111
def __init__(self):
104-
self.left = None
105-
self.right = None
112+
self.children = [None] * 2
113+
114+
def insert(self, x):
115+
node = self
116+
for i in range(30, -1, -1):
117+
v = (x >> i) & 1
118+
if node.children[v] is None:
119+
node.children[v] = Trie()
120+
node = node.children[v]
121+
122+
def search(self, x):
123+
node = self
124+
res = 0
125+
for i in range(30, -1, -1):
126+
v = (x >> i) & 1
127+
if node.children[v ^ 1]:
128+
res = res << 1 | 1
129+
node = node.children[v ^ 1]
130+
else:
131+
res <<= 1
132+
node = node.children[v]
133+
return res
106134

107135
class Solution:
108136
def findMaximumXOR(self, nums: List[int]) -> int:
109-
self.root = Trie()
110-
self.highest = 30
111-
112-
def add(num):
113-
node = self.root
114-
for i in range(self.highest, -1, -1):
115-
bit = (num >> i) & 1
116-
if bit == 0:
117-
if node.left is None:
118-
node.left = Trie()
119-
node = node.left
120-
else:
121-
if node.right is None:
122-
node.right = Trie()
123-
node = node.right
124-
125-
def cal(num):
126-
node = self.root
127-
res = 0
128-
for i in range(self.highest, -1, -1):
129-
bit = (num >> i) & 1
130-
if bit == 0:
131-
if node.right:
132-
res = res * 2 + 1
133-
node = node.right
134-
else:
135-
res = res * 2
136-
node = node.left
137-
else:
138-
if node.left:
139-
res = res * 2 + 1
140-
node = node.left
141-
else:
142-
res = res * 2
143-
node = node.right
144-
return res
145-
146-
res = 0
147-
for i in range(1, len(nums)):
148-
add(nums[i - 1])
149-
res = max(res, cal(nums[i]))
150-
return res
137+
trie = Trie()
138+
for v in nums:
139+
trie.insert(v)
140+
return max(trie.search(v) for v in nums)
151141
```
152142

153143
### **Java**
@@ -183,216 +173,154 @@ class Solution {
183173
}
184174
```
185175

186-
前缀树
176+
前缀树
187177

188178
```java
189-
class Solution {
190-
private static final int HIGHEST = 30;
191-
private Trie root;
192-
193-
public int findMaximumXOR(int[] nums) {
194-
int res = 0;
195-
root = new Trie();
196-
for (int i = 1; i < nums.length; ++i) {
197-
add(nums[i - 1]);
198-
res = Math.max(res, cal(nums[i]));
179+
class Trie {
180+
Trie[] children = new Trie[2];
181+
182+
void insert(int x) {
183+
Trie node = this;
184+
for (int i = 30; i >= 0; --i) {
185+
int v = (x >> i) & 1;
186+
if (node.children[v] == null) {
187+
node.children[v] = new Trie();
188+
}
189+
node = node.children[v];
199190
}
200-
return res;
201191
}
202192

203-
private int cal(int num) {
204-
Trie node = root;
193+
int search(int x) {
194+
Trie node = this;
205195
int res = 0;
206-
for (int i = HIGHEST; i >= 0; --i) {
207-
int bit = (num >> i) & 1;
208-
if (bit == 0) {
209-
if (node.right != null) {
210-
res = res * 2 + 1;
211-
node = node.right;
212-
} else {
213-
res = res * 2;
214-
node = node.left;
215-
}
196+
for (int i = 30; i >= 0; --i) {
197+
int v = (x >> i) & 1;
198+
if (node.children[v ^ 1] != null) {
199+
res = res << 1 | 1;
200+
node = node.children[v ^ 1];
216201
} else {
217-
if (node.left != null) {
218-
res = res * 2 + 1;
219-
node = node.left;
220-
} else {
221-
res = res * 2;
222-
node = node.right;
223-
}
202+
res <<= 1;
203+
node = node.children[v];
224204
}
225205
}
226206
return res;
227207
}
208+
}
228209

229-
private void add(int num) {
230-
Trie node = root;
231-
for (int i = HIGHEST; i >= 0; --i) {
232-
int bit = (num >> i) & 1;
233-
if (bit == 0) {
234-
if (node.left == null) {
235-
node.left = new Trie();
236-
}
237-
node = node.left;
238-
} else {
239-
if (node.right == null) {
240-
node.right = new Trie();
241-
}
242-
node = node.right;
243-
}
210+
class Solution {
211+
public int findMaximumXOR(int[] nums) {
212+
Trie trie = new Trie();
213+
int ans = 0;
214+
for (int v : nums) {
215+
trie.insert(v);
216+
ans = Math.max(ans, trie.search(v));
244217
}
218+
return ans;
245219
}
246220
}
247-
248-
class Trie {
249-
public Trie left;
250-
public Trie right;
251-
}
252221
```
253222

254223
### **C++**
255224

256225
```cpp
257226
class Trie {
258227
public:
259-
Trie* left;
260-
Trie* right;
261-
};
262-
263-
class Solution {
264-
public:
265-
int highest = 30;
266-
Trie* root;
228+
vector<Trie*> children;
229+
string v;
230+
Trie() : children(2) {}
267231

268-
int findMaximumXOR(vector<int>& nums) {
269-
root = new Trie();
270-
int res = 0;
271-
for (int i = 1; i < nums.size(); ++i)
232+
void insert(int x) {
233+
Trie* node = this;
234+
for (int i = 30; ~i; --i)
272235
{
273-
add(nums[i - 1]);
274-
res = max(res, cal(nums[i]));
236+
int v = (x >> i) & 1;
237+
if (!node->children[v]) node->children[v] = new Trie();
238+
node = node->children[v];
275239
}
276-
return res;
277240
}
278241

279-
int cal(int num) {
280-
Trie* node = root;
242+
int search(int x) {
243+
Trie* node = this;
281244
int res = 0;
282-
for (int i = highest; i >= 0; --i)
245+
for (int i = 30; ~i; --i)
283246
{
284-
int bit = (num >> i) & 1;
285-
if (bit == 0)
247+
int v = (x >> i) & 1;
248+
if (node->children[v ^ 1])
286249
{
287-
if (node->right)
288-
{
289-
res = res * 2 + 1;
290-
node = node->right;
291-
}
292-
else
293-
{
294-
res = res * 2;
295-
node = node->left;
296-
}
250+
res = res << 1 | 1;
251+
node = node->children[v ^ 1];
297252
}
298253
else
299254
{
300-
if (node->left)
301-
{
302-
res = res * 2 + 1;
303-
node = node->left;
304-
}
305-
else
306-
{
307-
res = res * 2;
308-
node = node->right;
309-
}
255+
res <<= 1;
256+
node = node->children[v];
310257
}
311258
}
312259
return res;
313260
}
261+
};
314262

315-
void add(int num) {
316-
Trie* node = root;
317-
for (int i = highest; i >= 0; --i)
263+
class Solution {
264+
public:
265+
int findMaximumXOR(vector<int>& nums) {
266+
Trie* trie = new Trie();
267+
int ans = 0;
268+
for (int v : nums)
318269
{
319-
int bit = (num >> i) & 1;
320-
if (bit == 0)
321-
{
322-
if (!node->left) node->left = new Trie();
323-
node = node->left;
324-
}
325-
else
326-
{
327-
if (!node->right) node->right = new Trie();
328-
node = node->right;
329-
}
270+
trie->insert(v);
271+
ans = max(ans, trie->search(v));
330272
}
273+
return ans;
331274
}
332275
};
333276
```
334277
335278
### **Go**
336279
337280
```go
338-
const highest = 30
281+
type Trie struct {
282+
children [26]*Trie
283+
}
339284
340-
type trie struct {
341-
left, right *trie
285+
func newTrie() *Trie {
286+
return &Trie{}
342287
}
343288
344-
func (root *trie) add(num int) {
345-
node := root
346-
for i := highest; i >= 0; i-- {
347-
bit := (num >> i) & 1
348-
if bit == 0 {
349-
if node.left == nil {
350-
node.left = &trie{}
351-
}
352-
node = node.left
353-
} else {
354-
if node.right == nil {
355-
node.right = &trie{}
356-
}
357-
node = node.right
289+
func (this *Trie) insert(x int) {
290+
node := this
291+
for i := 30; i >= 0; i-- {
292+
v := (x >> i) & 1
293+
if node.children[v] == nil {
294+
node.children[v] = newTrie()
358295
}
296+
node = node.children[v]
359297
}
360298
}
361299
362-
func (root *trie) cal(num int) int {
363-
node := root
300+
func (this *Trie) search(x int) int {
301+
node := this
364302
res := 0
365-
for i := highest; i >= 0; i-- {
366-
bit := (num >> i) & 1
367-
if bit == 0 {
368-
if node.right != nil {
369-
res = res*2 + 1
370-
node = node.right
371-
} else {
372-
res = res * 2
373-
node = node.left
374-
}
303+
for i := 30; i >= 0; i-- {
304+
v := (x >> i) & 1
305+
if node.children[v^1] != nil {
306+
res = res<<1 | 1
307+
node = node.children[v^1]
375308
} else {
376-
if node.left != nil {
377-
res = res*2 + 1
378-
node = node.left
379-
} else {
380-
res = res * 2
381-
node = node.right
382-
}
309+
res <<= 1
310+
node = node.children[v]
383311
}
384312
}
385313
return res
386314
}
387315
388316
func findMaximumXOR(nums []int) int {
389-
root := &trie{}
390-
res := 0
391-
for i := 1; i < len(nums); i++ {
392-
root.add(nums[i-1])
393-
res = max(res, root.cal(nums[i]))
317+
trie := newTrie()
318+
ans := 0
319+
for _, v := range nums {
320+
trie.insert(v)
321+
ans = max(ans, trie.search(v))
394322
}
395-
return res
323+
return ans
396324
}
397325
398326
func max(a, b int) int {

0 commit comments

Comments
 (0)