最大异或值

求最大异或值可以通过字典树进行求解。

  • 首先把每一个数字根据从高位到低位每位是0还是1建字典树。
  • 其次把每一个数字按位取反
  • 最后把每一个数字按位在字典树中进行查询,如果节点存在,则结果加上这个值,如果节点不存在,则走另一个节点。(因为建树的时候,每个数字都是32位,所以查询的时候,不会存在分支长度小于32的情况)

按位取反

1
num=~num;

如果按位遍历数字

1
2
3
4
for(int i=31;i>=0;i--)
{
int k=(num>>i)&1;
}

定义最小值最大值

1
2
#define INT_MIN 0x80000000
#define INT_MAX 0x7fffffff

描述

给定一些数,求这些数中两个数的异或值最大的那个值

input

第一行为数字个数n,1 <= n <= 10 ^ 5。接下来n行每行一个32位有符号非负整数。

output

任意两数最大异或值

Sample Input

3
3
7
9

Sample Output

14

COJ 1216题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<stdio.h>
#define N 100005
#define INT_MIN 0x80000000
int num[N];
struct trie
{
trie* next[2];
trie()
{
next[0] = NULL;
next[1] = NULL;
}
}root;

void insert(int num)
{

trie* p = &root;
for (int i = 31; i>=0; i--)
{
int k = (num >> i) & 1;
if (p->next[k] == NULL)
{
p->next[k] = new trie();
}
p = p->next[k];
}
}

int search(int num)
{

int result = 0;
num = ~num;
trie* p = &root;
for (int i = 31; i >= 0; i--)
{
int k = (num >> i) & 1;
if (k == 1)
{
if (p->next[1] != NULL)
{
result += 1 << i;
p = p->next[1];
}
else
{
p = p->next[0];
}
}
else
{
if (p->next[0] != NULL)
{
result += 1 << i;
p = p->next[0];
}
else
{
p = p->next[1];
}
}
}
return result;
}

int main()
{

int n;
while (scanf("%d", &n) != EOF)
{
for (int i = 0; i<n; i++)
{
scanf("%d", &num[i]);
insert(num[i]);
}
int MAX = INT_MIN;
for (int i = 0; i<n; i++)
{
int temp = search(num[i]);
if (temp>MAX)
{
MAX = temp;
}
}
printf("%d\n", MAX);
}
return 0;
}