1. 程式人生 > 其它 >leetcode-421 陣列中兩個數的最大異或值 字首樹

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