LeetCode 421. 数组中两个数的最大异或值
421. 數組中兩個數的最大異或值
Idea
假設選擇了數組中的元素ai和aj使得它們達到最大按位異或結果x:x=ai⊕ajx=a_{i}⊕a_{j}x=ai?⊕aj?,其中⊕表示按位異或運算。
根據異或運算的性質,x=ai⊕ajx=a_{i}⊕a_{j}x=ai?⊕aj?等價于aj=ai⊕xa_{j}=a_{i}⊕xaj?=ai?⊕x,根據這一變換,可以設計一種[從高位到低位依次確定x二進制表示的每一位]的方法,以此得到x的值。
數組中的元素都在[0, 231)的范圍內,可以將每一個數都表示為一個長度為31位的二進制數(不滿31位補前導0)字符串,然后可以從最高位第30個二進制位開始依次確定x的每一位是0還是1。
由于需要找出最大的x,因此在枚舉每一位時,需要先判斷x的這一位是否能取到1,如果能,就取這一位為1,否則取這一位為0。
將字符串放入字典樹中,那么在字符串中查詢一個字符串的過程,就是從高位開始確定每一個二進制位的過程。
x=ai⊕ajx=a_{i}⊕a_{j}x=ai?⊕aj?,枚舉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 Listclass Trie:def __init__(self):self.left, self.right = None, Noneclass Solution:def findMaximumXOR(self, nums: List[int]) -> int:root = Trie()HIGH_BIT = 30def add(num: int) -> None:cur = rootfor k in range(HIGH_BIT, -1, -1):bit = (num >> k) & 1if bit == 0:if not cur.left:cur.left = Trie()cur = cur.leftelse:if not cur.right:cur.right = Trie()cur = cur.rightdef check(num: int) -> int:cur = rootx = 0for k in range(HIGH_BIT, -1, -1):bit = (num >> k) & 1if bit == 0:if cur.right:cur = cur.rightx = x * 2 + 1else:cur = cur.leftx = x * 2else:if cur.left:cur = cur.leftx = x * 2 + 1else:cur = cur.rightx = x * 2return xn, x = len(nums), 0for i in range(1, n):add(nums[i - 1])x = max(x, check(nums[i]))return x總結
以上是生活随笔為你收集整理的LeetCode 421. 数组中两个数的最大异或值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 变量创建过程
- 下一篇: Spark is not running