Skip to content

Latest commit

 

History

History

1707

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

You are given an array nums consisting of non-negative integers. You are also given a queries array, where queries[i] = [xi, mi].

The answer to the ith query is the maximum bitwise XOR value of xi and any element of nums that does not exceed mi. In other words, the answer is max(nums[j] XOR xi) for all j such that nums[j] <= mi. If all elements in nums are larger than mi, then the answer is -1.

Return an integer array answer where answer.length == queries.length and answer[i] is the answer to the ith query.

 

Example 1:

Input: nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]
Output: [3,3,7]
Explanation:
1) 0 and 1 are the only two integers not greater than 1. 0 XOR 3 = 3 and 1 XOR 3 = 2. The larger of the two is 3.
2) 1 XOR 2 = 3.
3) 5 XOR 2 = 7.

Example 2:

Input: nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]]
Output: [15,-1,5]

 

Constraints:

  • 1 <= nums.length, queries.length <= 105
  • queries[i].length == 2
  • 0 <= nums[j], xi, mi <= 109

Companies: Google

Related Topics:
Array, Bit Manipulation, Trie

Similar Questions:

Hints:

  • In problems involving bitwise operations, we often think on the bits level. In this problem, we can think that to maximize the result of an xor operation, we need to maximize the most significant bit, then the next one, and so on.
  • If there's some number in the array that is less than m and whose the most significant bit is different than that of x, then xoring with this number maximizes the most significant bit, so I know this bit in the answer is 1.
  • To check the existence of such numbers and narrow your scope for further bits based on your choice, you can use trie.
  • You can sort the array and the queries, and maintain the trie such that in each query the trie consists exactly of the valid elements.

Solution 1. Trie

// OJ: https://leetcode.com/problems/maximum-xor-with-an-element-from-array/
// Author: github.com/lzl124631x
// Time: O(A + Q)
// Space: O(A)
struct TrieNode {
    TrieNode *next[2] = {};
    int minVal = INT_MAX;
};
class Solution {
    void addNumber(TrieNode *node, int n) {
        for (int i = 31; i >= 0; --i) {
            int b = n >> i & 1;
            if (!node->next[b]) node->next[b] = new TrieNode();
            node = node->next[b];
            node->minVal = min(node->minVal, n);
        }
    }
    int maxXor(TrieNode *node, int n, int mx) {
        int ans = 0;
        for (int i = 31; i >= 0; --i) {
            int b = n >> i & 1, r = 1 - b;
            if (node->next[r] && node->next[r]->minVal <= mx) node = node->next[r], ans |= (1 << i);
            else if (node->next[b] && node->next[b]->minVal <= mx) node = node->next[b];
            else return -1;
        }
        return ans;
    }
public:
    vector<int> maximizeXor(vector<int>& A, vector<vector<int>>& Q) {
        TrieNode root;
        for (int n : A) addNumber(&root, n);
        vector<int> ans;
        for (auto &q : Q) {
            int x = q[0], m = q[1];
            ans.push_back(maxXor(&root, x, m));
        }
        return ans;
    }
};

Solution 2. Offline Query + Trie

// OJ: https://leetcode.com/problems/maximum-xor-with-an-element-from-array/
// Author: github.com/lzl124631x
// Time: O(QlogQ + AlogA + Q + A)
// Space: O(Q + A)
struct TrieNode {
    TrieNode *next[2] = {};
};
class Solution {
    void addNumber(TrieNode *node, int n) {
        for (int i = 31; i >= 0; --i) {
            int b = n >> i & 1;
            if (!node->next[b]) node->next[b] = new TrieNode();
            node = node->next[b];
        }
    }
    int find(TrieNode *node, int n) {
        int ans = 0;
        for (int i = 31; i >= 0; --i) {
            int b = n >> i & 1, r = 1 - b;
            if (node->next[r]) node = node->next[r], ans |= (1 << i);
            else node = node->next[b];
        }
        return ans;
    }
public:
    vector<int> maximizeXor(vector<int>& A, vector<vector<int>>& Q) {
        sort(begin(A), end(A));
        for (int i = 0; i < Q.size(); ++i) Q[i].push_back(i);
        sort(begin(Q), end(Q), [](auto &a, auto &b) { return a[1] < b[1]; });
        int i = 0, N = A.size();
        TrieNode root;
        vector<int> ans(Q.size());
        for (auto &q : Q) {
            int x = q[0], m = q[1], idx = q[2];
            while (i < N && A[i] <= m) addNumber(&root, A[i++]);
            ans[idx] = i == 0 ? -1 : find(&root, x);
        }
        return ans;
    }
};