[Leetcode421](python): 数组中两个数之间最

2020-01-16  本文已影响0人  myFamily329
1. 题目来源
2. 题目描述

给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i, j < n 。你能在O(n)的时间解决这个问题吗?
示例:

输入: [3, 10, 5, 25, 2, 8]

输出: 28

解释: 最大的结果是 5 ^ 25 = 28.
3. 解题思路

根据Trie Tree(字典树/前缀树/单词查找树)对Trie基本结构的描述,编写构建结点,以及构建trie树,以及trie树的基本操作方法。
本题的解题思路:Trie树 + 位运算

【Trie树】Trie树建立的思路,整数在存储时需要32bit,因此可以把整数看作为含有32字符的字符串,其中每个字符为0或1,则可以使用二叉树构建前缀树。从高位到低位进行构建,其中左结点为1,右结点为0.
构建前缀树
【位运算找最大异或值】如何找到最大值异或,两个数异或得到一个尽可能大的数,则第一个1出现的位数越高则数越大,所以可以从最高位开始,找和它相反的数,如果存在这这个数异或即得到最大异或值,若不存在则,则继续相下找,直到找到相异的位。

对于25 (0000 0000 0000 0000 0000 0000 0001 1001) 而言,使得异或结果最大的数x为0000 0000 0000 0000 0000 0000 000* ****
从根节点开始搜索,node = root,直至到第5位,当前node为第6位右分支。
25第5位为1,则x的第5位为0,结果为最大,选择右分支,node = node.zero;
25第4位为1,则x的第4位为0,结果为最大,选择右分支,node = node.zero;
25第3位为0,则x的第3位为1,结果为最大,选择左分支,node = node.one;
25第2位为0,则x的第2位为1,结果为最大,当前node.one为空,所以选择node.zero, node = node.zero;
25第1位为1,则x的第1位为0,结果为最大,当前node.zero为空,所以选择node.one, node = node.one;最终找到x为5(00101)。
对于数组中每一个数进行上述操作,更新最大异或值。
建立Trie树的时间复杂度是O(32n),这里的32即Trie树的键值最大长度;Trie树的高度为32,因此查找每个数的最大异或值得时间复杂度是O(32n),合起来是O(64n)也即时间复杂度为O(n)

4. 编程实现
Python
class TrieNode:
    def __init__(self):
        self.one = None
        self.zero = None

class Solution:
    def findMaximumXOR(self, nums: List[int]) -> int:
        #构建前缀树
        root = TrieNode()

        for num in nums:
            node = root
            #从最高位开始到最低位顺序进行构建
            for i in range(31, -1, -1):
                temp = num & (1 << i)
                if temp:
                    if not node.one:
                        node.one = TrieNode()
                    node = node.one
                else:
                    if not node.zero:
                        node.zero = TrieNode()
                    node = node.zero
        
        #求最大异或值
        res = 0 
        for num in nums:
            node = root
            xor = 0
            for i in range(31, -1, -1):
                temp = num & (1 << i)
                if node.zero and temp:
                    node = node.zero
                    #对于2进制最终转换为10进制的结果1/0 * 2^n + ...
                    xor += 1 << i
                elif node.one and not temp:
                    node = node.one
                    xor += 1 << i
                else:
                    node = node.one or node.zero
            res = max(res, xor)
        return res
                
参考学习:

https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/discuss/130427/()-92
http://bookshadow.com/weblog/2016/10/15/leetcode-maximum-xor-of-two-numbers-in-an-array/

上一篇下一篇

猜你喜欢

热点阅读