【算法思考记录】力扣2935. 找出强数对的最大异或值 II【Python3,0-1字典树,滑动窗口】

强数对的最大异或值求解分析

题目解析

题目编号2935要求我们从一个整数数组 nums 中选出两个整数,形成一个所谓的“强数对”,并求出所有可能强数对的最大按位异或(XOR)值。这里的强数对定义为两个整数 xy 满足 |x - y| <= min(x, y)

解题思路

1. 0-1字典树(Trie)的应用

为了有效求解最大异或值,我们使用了一种特殊的数据结构——0-1字典树(Trie)。这种结构能够高效地处理和存储大量整数的二进制表示,特别适合用来查询一个数与一组数异或后能得到的最大值。

2. 滑动窗口

由于题目中的强数对条件 |x - y| <= min(x, y),我们可以通过排序和滑动窗口来维护这个条件。具体来说,我们保持一个窗口,确保窗口内的所有数 x 满足 2 * x >= y(y是窗口的最大值)。这样,窗口内的任意两数都能形成强数对。

代码解析

class Node:

    def __init__(self):
        self.children = [None, None]
        self.cnt = 0 # 使用cnt来记录子树的大小

class Trie:
    HIGH_BIT = 20 # 题目数据范围表示,最高位有20位

    def __init__(self):
        self.root = Node()
    
    # 插入一个数字,相当于把这个数字的各位上的0和1记录到Trie中
    def insert(self, val: int) -> None:
        cur = self.root # 变量cur作为一个游标,代表目前的位置
        for i in range(Trie.HIGH_BIT, -1, -1):
            bit = (val >> i) & 1 # 从最高位出发,检查该位是0还是1
            if cur.children[bit] is None:
                cur.children[bit] = Node() # 如果不存在该子树,则创建一个
            cur = cur.children[bit]
            cur.cnt += 1 # 代表该子树大小 + 1
        
        return cur
    
    # 删除掉一个数字的各位0和1对应的节点
    def remove(self, val: int) -> None:
        cur = self.root
        for i in range(Trie.HIGH_BIT, -1, -1):
            bit = (val >> i) & 1
            cur = cur.children[bit]
            cur.cnt -= 1 # 把这个数字的各位0和1对应的节点减去1,代表该子树-1
        return cur
    
    # 查询能与数字val异或得出的最大和,
    # 其实就是不断查询与val各位上相反的节点
    def max_xor(self, val: int) -> int:
        cur = self.root
        ans = 0
        for i in range(Trie.HIGH_BIT, -1, -1):
            bit = (val >> i) & 1
            inv_bit = bit ^ 1 # 与val在第i位相反的位
            # 如果存在可以异或为1的位
            if cur.children[inv_bit] is not None and cur.children[inv_bit].cnt != 0:
                ans |= 1 << i # 加入到ans中
                cur = cur.children[inv_bit]
            else:
                cur = cur.children[bit] # 如果不存在inv_bit,就只能走变成0的位咯
        return ans

class Solution:
    def maximumStrongPairXor(self, nums: List[int]) -> int:
        nums.sort()
        trie = Trie()
        ans = left = 0
        for y in nums:
            trie.insert(y)
            # 为了保证 2 * x >= y,要丢弃不满足该要求的节点
            while nums[left] * 2 < y:
                trie.remove(nums[left])
                left += 1
            ans = max(ans, trie.max_xor(y))
        return ans

总结

这个解法结合了0-1字典树和滑动窗口两种算法思想,有效地解决了题目中的最大异或值问题。字典树在处理二进制表示和求最大异或值时表现出色,而滑动窗口则能保证强数对的条件。通过这种方法,我们可以高效地求解出最大的异或值。

你可能感兴趣的:(算法,leetcode,python,数据结构,职场和发展)