Skip to content

1803. Count Pairs With XOR in a Range

Description

Given a (0-indexed) integer array nums and two integers low and high, return the number of nice pairs.

A nice pair is a pair (i, j) where 0 <= i < j < nums.length and low <= (nums[i] XOR nums[j]) <= high.

 

Example 1:

Input: nums = [1,4,2,7], low = 2, high = 6
Output: 6
Explanation: All nice pairs (i, j) are as follows:
    - (0, 1): nums[0] XOR nums[1] = 5 
    - (0, 2): nums[0] XOR nums[2] = 3
    - (0, 3): nums[0] XOR nums[3] = 6
    - (1, 2): nums[1] XOR nums[2] = 6
    - (1, 3): nums[1] XOR nums[3] = 3
    - (2, 3): nums[2] XOR nums[3] = 5

Example 2:

Input: nums = [9,8,4,2,1], low = 5, high = 14
Output: 8
Explanation: All nice pairs (i, j) are as follows:
​​​​​    - (0, 2): nums[0] XOR nums[2] = 13
    - (0, 3): nums[0] XOR nums[3] = 11
    - (0, 4): nums[0] XOR nums[4] = 8
    - (1, 2): nums[1] XOR nums[2] = 12
    - (1, 3): nums[1] XOR nums[3] = 10
    - (1, 4): nums[1] XOR nums[4] = 9
    - (2, 3): nums[2] XOR nums[3] = 6
    - (2, 4): nums[2] XOR nums[4] = 5

 

Constraints:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 2 * 104
  • 1 <= low <= high <= 2 * 104

 

Solutions

Solution: Trie

  • Time complexity: O(nlog(Max(nums, high)))
  • Space complexity: O(nlog(Max(nums, high)))

 

JavaScript

js
/**
 * @param {number[]} nums
 * @param {number} low
 * @param {number} high
 * @return {number}
 */
const countPairs = function (nums, low, high) {
  const trie = new TrieNode();
  const maxNum = Math.max(...nums, high);
  const log = Math.ceil(Math.log2(maxNum));
  let result = 0;

  const insertNum = num => {
    let current = trie;

    for (let index = log; index >= 0; index--) {
      const bit = (num >> index) & 1;

      if (!current.children[bit]) {
        current.children[bit] = new TrieNode();
      }

      current = current.children[bit];
      current.count += 1;
    }
  };

  const getCount = (num, limit) => {
    let count = 0;
    let current = trie;

    for (let index = log; index >= 0; index--) {
      const bit = (num >> index) & 1;
      const limitBit = (limit >> index) & 1;

      if (limitBit) {
        if (current.children[bit]) {
          count += current.children[bit].count;
        }

        current = current.children[bit ^ 1];
      } else {
        current = current.children[bit];
      }

      if (!current) return count;
    }

    return count;
  };

  for (const num of nums) {
    result += getCount(num, high + 1) - getCount(num, low);
    insertNum(num);
  }

  return result;
};

class TrieNode {
  children = [null, null];
  count = 0;
}

Released under the MIT license