编辑
2023-11-04
算法题
00
请注意,本文编写于 553 天前,最后修改于 553 天前,其中某些信息可能已经过时。

目录

解法一:哈希表
解法二:trie树

image.png

解法一:哈希表

假设最终的最大异或结果为 maxXOR,我们可以从最高位开始构建这个结果。我们使用一个掩码 mask 来构建当前位的前缀。初始时,mask 为 0。

对于每一位,我们通过遍历数组 nums,计算所有数的当前位前缀,然后将其加入一个集合 prefixes 中。集合 prefixes 存储了所有可能的当前位前缀。

接下来,我们假设当前位为 1,构建一个潜在的最大异或结果 potentialMax。我们通过将 maxXOR 的当前位设置为 1 来构建 potentialMax。例如,如果 maxXOR 的二进制表示为 1010,而当前位为第 3 位,那么 potentialMax 的二进制表示为 1110。

然后,我们遍历 prefixes 集合中的每个前缀 prefix。我们检查集合中是否存在一个前缀与 potentialMax ^ prefix 相等。这里的 ^ 是按位异或运算符。如果存在这样的前缀,说明最大异或结果的当前位可以为 1,我们更新 maxXOR 为 potentialMax,并跳出循环,继续处理下一位。如果不存在这样的前缀,则最大异或结果的当前位必须为 0,我们不需要更新 maxXOR,继续处理下一位。

通过这种方式,我们逐位确定了最大异或结果 maxXOR。最后,返回得到的 maxXOR 即为所求。

这种方法的时间复杂度为 O(32N) = O(N),其中 N 是数组的长度。因为一个整数的二进制表示最多有 32 位,所以我们需要进行 32 次循环来确定最大异或结果的每一位。在每一次循环中,我们需要遍历数组 nums,计算当前位的前缀,所以时间复杂度为 O(N)。总的时间复杂度为 O(32N) = O(N)。这种方法的空间复杂度为 O(1)。

cpp
class Solution { public: int findMaximumXOR(vector<int>& nums) { int maxXOR = 0; int mask = 0; for (int i = 31; i >= 0; i--) { mask |= (1 << i); // 构建当前位的掩码 unordered_set<int> prefixes; // 用于存储当前位前缀的集合 for (int num : nums) { prefixes.insert(num & mask); // 将当前位的前缀加入集合 } int potentialMax = maxXOR | (1 << i); // 假设当前位为 1 for (int prefix : prefixes) { if (prefixes.count(potentialMax ^ prefix)) { // 如果存在一个前缀与 potentialMax^prefix 相等 // 则最大异或值的当前位可以为 1 maxXOR = potentialMax; break; } } } return maxXOR; } };

解法二:trie树

我们定义了 TrieNode 类表示 Trie 树的节点。每个节点有两个子节点,分别表示当前位为 0 和 1 时的情况。

接下来,我们定义了 Trie 类表示 Trie 树。Trie 类有一个根节点,并提供了插入和查找最大异或值的方法。

在插入方法 insert 中,我们从当前数的最高位开始遍历,将每一位作为索引,根据当前位的值选择相应的子节点。如果子节点为空,我们创建一个新的节点。然后,将当前节点移动到下一位的子节点,继续进行插入操作。最终,将整个数的二进制表示插入 Trie 树中。

在查找最大异或值的方法 findMaxXOR 中,我们从当前数的最高位开始遍历,依次判断当前位的相反位是否存在。如果存在相反位,说明最大异或值的当前位可以为 1,我们将当前位的值设为 1,并将当前节点移动到相反位的子节点。如果不存在相反位,说明最大异或值的当前位必须为 0,我们将当前位的值设为 0,并将当前节点移动到当前位的子节点。通过这样的遍历,我们可以得到最大异或值。

cpp
class Solution { public: // Trie 节点 class TrieNode { public: TrieNode* next[2]; TrieNode() { next[0] = nullptr; next[1] = nullptr; } }; // Trie 树 class Trie { public: TrieNode* root; Trie() { root = new TrieNode(); } void insert(int num) { TrieNode* curr = root; for (int i = 31; i >= 0; i--) { int bit = (num >> i) & 1; if (curr->next[bit] == nullptr) { curr->next[bit] = new TrieNode(); } curr = curr->next[bit]; } } int findMaxXOR(int num) { int maxXOR = 0; TrieNode* curr = root; for (int i = 31; i >= 0; i--) { int bit = (num >> i) & 1; int oppositeBit = bit ^ 1; // 获取与当前位相反的位 if (curr->next[oppositeBit] != nullptr) { maxXOR |= (1 << i); // 如果存在相反位,则当前位可以为 1 curr = curr->next[oppositeBit]; } else { curr = curr->next[bit]; } } return maxXOR; } }; int findMaximumXOR(vector<int>& nums) { Trie trie; int maxXOR = 0; for (int num : nums) { trie.insert(num); int currXOR = trie.findMaxXOR(num); maxXOR = max(maxXOR, currXOR); } return maxXOR; } };

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!