LeetCode 421. 数组中两个数的最大异或值

Posted Alex Hub

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 421. 数组中两个数的最大异或值相关的知识,希望对你有一定的参考价值。

421. 数组中两个数的最大异或值

Idea

假设选择了数组中的元素ai和aj使得它们达到最大按位异或结果x: x = a i ⊕ a j x=a_{i}⊕a_{j} x=aiaj,其中⊕表示按位异或运算。

根据异或运算的性质, x = a i ⊕ a j x=a_{i}⊕a_{j} x=aiaj等价于 a j = a i ⊕ x a_{j}=a_{i}⊕x aj=aix,根据这一变换,可以设计一种[从高位到低位依次确定x二进制表示的每一位]的方法,以此得到x的值。

数组中的元素都在[0, 231)的范围内,可以将每一个数都表示为一个长度为31位的二进制数(不满31位补前导0)字符串,然后可以从最高位第30个二进制位开始依次确定x的每一位是0还是1。

由于需要找出最大的x,因此在枚举每一位时,需要先判断x的这一位是否能取到1,如果能,就取这一位为1,否则取这一位为0。

将字符串放入字典树中,那么在字符串中查询一个字符串的过程,就是从高位开始确定每一个二进制位的过程。

x = a i ⊕ a j x=a_{i}⊕a_{j} x=aiaj,枚举ai,将a0, a1, …, ai-1作为aj放入字典树,希望找到使得x达到最大值的aj

从字典树的根节点开始进行遍历,遍历的[参照对象]为ai,根据ai的第x个二进制位时0还是1确定应该走哪个子节点。

假设当前遍历到第k个二进制位:

  • 如果ai的第k个二进制位为0,那么应该往表示1的子节点走。如果不存在表示1的子节点,就只能往表示0的子节点走。
  • 如果ai的第k个二进制位为1,那么应该往表示0的子节点走。如果不存在表示0的子节点,就只能往表示1的子节点走。

遍历完所有的31个二进制位后,得到ai可以通过异或运算得到的最大x。

Code

Python

from typing import List


class Trie:
	def __init__(self):
		self.left, self.right = None, None


class Solution:
	def findMaximumXOR(self, nums: List[int]) -> int:
		root = Trie()
		HIGH_BIT = 30

		def add(num: int) -> None:
			cur = root
			for k in range(HIGH_BIT, -1, -1):
				bit = (num >> k) & 1
				if bit == 0:
					if not cur.left:
						cur.left = Trie()
					cur = cur.left
				else:
					if not cur.right:
						cur.right = Trie()
					cur = cur.right

		def check(num: int) -> int:
			cur = root
			x = 0
			for k in range(HIGH_BIT, -1, -1):
				bit = (num >> k) & 1
				if bit == 0:
					if cur.right:
						cur = cur.right
						x = x * 2 + 1
					else:
						cur = cur.left
						x = x * 2
				else:
					if cur.left:
						cur = cur.left
						x = x * 2 + 1
					else:
						cur = cur.right
						x = x * 2
			return x
		
		n, x = len(nums), 0
		for i in range(1, n):
			add(nums[i - 1])
			x = max(x, check(nums[i]))
		return x

以上是关于LeetCode 421. 数组中两个数的最大异或值的主要内容,如果未能解决你的问题,请参考以下文章

leetcode-421-数组中两个数的最大异或值*(前缀树)

LeetCode 421. 数组中两个数的最大异或值

LeetCode 421. 数组中两个数的最大异或值 Java 前缀树

LeetCode 421. 数组中两个数的最大异或值 Java 前缀树

LeetCode 421. 数组中两个数的最大异或值 Java 前缀树

追寻最优美的代码 leetcode 421. 数组中两个数的最大异或值