Given an integer array nums, return the maximum result of nums[i] XOR nums[j], where 0 &lt;= i &lt;= j &lt; n.

&nbsp;
Example 1:

Input: nums = [3,10,5,25,2,8]
Output: 28
Explanation: The maximum result is 5 XOR 25 = 28.


Example 2:

Input: nums = [14,70,53,83,49,91,36,80,92,51,66,70]
Output: 127


&nbsp;
Constraints:


	1 &lt;= nums.length &lt;= 2 * 105
	0 &lt;= nums[i] &lt;= 231 - 1


class Solution:
	def findMaximumXOR(self, nums: List[int]) -> int:
		TrieNode = lambda: defaultdict(TrieNode)
		root = TrieNode()
		for n in nums:
			cur = root
			for i in range(31,-1,-1):
				bit = 1 if n&(1<<i) else 0
				cur = cur[bit]
			cur['val']=n

		ans = 0
		for n in nums:        
			cur = root
			for i in range(31,-1,-1):
				bit = 1 if n&(1<<i) else 0
				if bit == 1:
					if 0 in cur: cur = cur[0]
					else: cur = cur[1]
				else: 
					if 1 in cur: cur = cur[1]
					else: cur = cur[0]
			ans = max(ans,cur['val']^n)

		return ans
class Node {
    Node[] links = new Node[2];
    
    public Node () {
        
    }
    
    boolean containsKey(int ind) {
        return links[ind] != null;
    }
    
    Node get(int ind) {
        return links[ind];
    }
    
    void put(int ind, Node node) {
        links[ind] = node;
    }
}

class Trie {
    private static Node root;
    
    public Trie() {
        root = new Node();
    }
    
    public static void insert(int num) {
        Node node = root;
        for (int i = 31; i >= 0; i--) {
            int bit = (num >> i) & 1;
            if (!node.containsKey(bit)) {
                node.put(bit, new Node());
            }
            node = node.get(bit);
        }
    }
    
    public static int getMax(int num) {
        Node node = root;
        int maxNum = 0;
        
        for (int i = 31; i >= 0; i--) {
            int bit = (num >> i) & 1;
            if (node.containsKey(1 - bit)) {
                maxNum = maxNum | (1 << i);
                node = node.get(1 - bit);
            }
            else {
                node = node.get(bit);
            }
        }
        return maxNum;
    }
}


class Solution {
    public int findMaximumXOR(int[] nums) {
        Trie trie = new Trie();
        
        for (int i = 0; i < nums.length; i++) {
            trie.insert(nums[i]);
        }
        
        int maxi = 0;
        for (int i = 0; i < nums.length; i++) {
            maxi = Math.max(maxi, trie.getMax(nums[i]));
        }
       return maxi;
    }
}
class Solution {
public:
    struct TrieNode {
        //trie with max 2 child, not taking any bool or 26 size value because no need
        TrieNode* one;
        TrieNode* zero;
    };
    void insert(TrieNode* root, int n) {
        TrieNode* curr = root;
        for (int i = 31; i >= 0; i--) {
            int bit = (n >> i) & 1;  //it will find 31st bit and check it is 1 or 0
            if (bit == 0) {
                if (curr->zero == nullptr) {   //if 0 then we will continue filling on zero side
                    TrieNode* newNode = new TrieNode();    
                    curr->zero = newNode;  
                }
                curr = curr->zero;   //increase cur to next zero position
            }
            else {
                //similarly if we get 1 
                if (curr->one == nullptr) {
                    TrieNode* newNode = new TrieNode();
                    curr->one = newNode;
                }
                curr = curr->one;
            }
        }
    }
     int findmax(TrieNode* root, int n) {
        TrieNode* curr = root;
        int ans = 0;
        for (int i = 31; i >= 0; i--) {
            int bit = (n >> i) & 1;
            if (bit == 1) {
                if (curr->zero != nullptr) {  //finding complement , if find 1 then we will check on zero side
                    ans += (1 << i); //push values in ans
                    curr = curr->zero;
                }
                else {
                    curr = curr->one;  //if we don't get then go to one's side
                }
            }
            else {
                //similarly on zero side if we get 0 then we will check on 1 s side
                if (curr->one != nullptr) {   
                    ans += (1 << i);
                    curr = curr->one;
                }
                else {
                    curr = curr->zero;
                }
            }
        }
        return ans;
    }

    int findMaximumXOR(vector<int>& nums) {
        int n = nums.size();
        TrieNode* root = new TrieNode();
        int ans = 0;
        for (int i = 0; i < n; i++) {
            insert(root, nums[i]);    //it will make trie by inserting values
        }
        for (int i = 1; i < n; i++) {
            ans = max(ans, findmax(root, nums[i]));  //find the necessary complementory values and maximum store
        }
        return ans;
    }
};
var findMaximumXOR = function(nums) {
    const trie = {};
    const add = (num) => {
        let p = trie;
        for(let i = 31; i >= 0; i--) {
            const isSet = (num >> i) & 1;
            if(!p[isSet]) p[isSet] = {};
            p = p[isSet];
        }
    }
    const xor = (num) => {
        let p = trie;
        let ans = 0;
        for(let i = 31; i >= 0; i--) {
            const isSet = ((num >> i) & 1);
            const opp = 1 - isSet;
            const hasOpp = p[opp];
            if(hasOpp) {
                ans = ans | (1<<i);
                p = p[opp];
            } else {
                p = p[isSet];
            }
        }
        return ans;
    }
    
    for(let num of nums) {
        add(num);
    }
    let max = 0;
    for(let num of nums) {
        max = Math.max(max, xor(num))
    }
    return max;
};
Maximum XOR of Two Numbers in an Array