leetcode-421 数组中两个数的最大异或值 前缀树
leetcode-421 数组中两个数的最大异或值 前缀树
1. 题目
给你一个整数数组 nums ,返回 nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n 。
2. 思路
-
暴力解法通过双层for循环求出最大的异或结果,时间复杂度为\(O(n^2)\) 超时
-
前缀树
一个整数的二进制串只有0和1,因此可以将所有位放在一颗前缀树中,在一棵前缀树中查找某个树的复杂度为O(logn),因此已知一棵字典树,查找树中与它最大异或值最大的复杂度为O(logn)
求异或值的最大值,应该让该结果中的每一个尽可能为1
查找过程:
输入数字不超过2^31,因此遍历该数的每一位,
-
如果该位为1,则在树中选择的节点为0,建立前缀树时,0作为左树,1作为右数,如果没有左树,则选择右树
-
如果该位为0,则在树中选择右树,若没有右树则选择左树
在查找时,如果选择的时不同的值,即\(0\bigoplus 1\),此时的异或结果为\(x=x*2+1\),增加了一位,且末位为1,
若是\(0\bigoplus 0\)和\(1\bigoplus 1\),此时的\(x=x*2\)
如图,对于25,和前缀树相比,第一位时1,则在前缀树第一层选择(0),第二位是1,前缀树中选择(0,0),第三位时0,前缀树中选择(0,0,1),第四位是0,前缀树中第四位本应选择1,但此时节点只有左节点,因此前缀树中选择(0,0,1,1),第五位是1,前缀树中选择(0,0,1,0,1)
-
3. Code
-
暴力解法
class Solution: def findMaximumXOR(self, nums: List[int]) -> int: res=float("-inf") length=len(nums) for i in range(length): for j in range(i,length): res=max(res,nums[i]^nums[j]) return res
-
前缀树
class TreeNode: def __init__(self,left=None, right=None): self.left = left self.right = right class Solution: def findMaximumXOR(self, nums: List[int]) -> int: root=TreeNode() def add(n): cur=root for k in range(30,-1,-1): bit=(n>>k)&1 if bit==0: if not cur.left: cur.left=TreeNode() cur=cur.left else: if not cur.right: cur.right=TreeNode() cur=cur.right def check(num): cur=root x=0 for i in range(30,-1,-1): bit=(num>>i)&1 if bit==0: if cur.right: cur=cur.right x=x*2+1 else: cur=cur.left x*=2 else: if cur.left: cur=cur.left x=x*2+1 else: cur=cur.right x*=2 return x x=0 for i in range(1,len(nums)): add(nums[i-1]) x=max(x,check(nums[i])) return x