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\)

    image-20210516211249200

    如图,对于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
    
posted @ 2021-10-16 10:38  流光之中  阅读(25)  评论(0编辑  收藏  举报