Skip to content

1938. Maximum Genetic Difference Query

Description

There is a rooted tree consisting of n nodes numbered 0 to n - 1. Each node's number denotes its unique genetic value (i.e. the genetic value of node x is x). The genetic difference between two genetic values is defined as the bitwise-XOR of their values. You are given the integer array parents, where parents[i] is the parent for node i. If node x is the root of the tree, then parents[x] == -1.

You are also given the array queries where queries[i] = [nodei, vali]. For each query i, find the maximum genetic difference between vali and pi, where pi is the genetic value of any node that is on the path between nodei and the root (including nodei and the root). More formally, you want to maximize vali XOR pi.

Return an array ans where ans[i] is the answer to the ith query.

 

Example 1:

Input: parents = [-1,0,1,1], queries = [[0,2],[3,2],[2,5]]
Output: [2,3,7]
Explanation: The queries are processed as follows:
- [0,2]: The node with the maximum genetic difference is 0, with a difference of 2 XOR 0 = 2.
- [3,2]: The node with the maximum genetic difference is 1, with a difference of 2 XOR 1 = 3.
- [2,5]: The node with the maximum genetic difference is 2, with a difference of 5 XOR 2 = 7.

Example 2:

Input: parents = [3,7,-1,2,0,7,0,2], queries = [[4,6],[1,15],[0,5]]
Output: [6,14,7]
Explanation: The queries are processed as follows:
- [4,6]: The node with the maximum genetic difference is 0, with a difference of 6 XOR 0 = 6.
- [1,15]: The node with the maximum genetic difference is 1, with a difference of 15 XOR 1 = 14.
- [0,5]: The node with the maximum genetic difference is 2, with a difference of 5 XOR 2 = 7.

 

Constraints:

  • 2 <= parents.length <= 105
  • 0 <= parents[i] <= parents.length - 1 for every node i that is not the root.
  • parents[root] == -1
  • 1 <= queries.length <= 3 * 104
  • 0 <= nodei <= parents.length - 1
  • 0 <= vali <= 2 * 105

 

Solutions

Solution: Trie + Depth-First Search

  • Time complexity: O((n+m)log(maxVal))
  • Space complexity: O((n+m)log(maxVal))

 

JavaScript

js
/**
 * @param {number[]} parents
 * @param {number[][]} queries
 * @return {number[]}
 */
const maxGeneticDifference = function (parents, queries) {
  const n = parents.length;
  const m = queries.length;
  const maxVal = Math.max(n, ...queries.map(([_, val]) => val));
  const bits = Math.ceil(Math.log2(maxVal));
  const tree = Array.from({ length: n }, () => []);
  const trie = new Trie(bits);
  const nodeQueries = Array.from({ length: n }, () => []);
  const result = Array.from({ length: m });
  let root = -1;

  const dfsTree = node => {
    trie.insert(node);

    for (const { index, val } of nodeQueries[node]) {
      result[index] = trie.maxXor(val);
    }

    for (const child of tree[node]) {
      dfsTree(child);
    }

    trie.remove(node);
  };

  for (let node = 0; node < n; node++) {
    const parent = parents[node];

    if (parent === -1) {
      root = node;
    } else {
      tree[parent].push(node);
    }
  }

  for (let index = 0; index < m; index++) {
    const [node, val] = queries[index];

    nodeQueries[node].push({ index, val });
  }

  dfsTree(root);

  return result;
};

class Node {
  constructor() {
    this.children = {};
    this.count = 0;
  }
}

class Trie {
  constructor(bits) {
    this.root = new Node();
    this.bits = bits;
  }

  insert(num) {
    let node = this.root;

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

      if (!node.children[bit]) {
        node.children[bit] = new Node();
      }

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

  remove(num) {
    let node = this.root;

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

      node = node.children[bit];
      node.count -= 1;
    }
  }

  maxXor(val) {
    let node = this.root;
    let result = 0;

    for (let index = this.bits; index >= 0; index--) {
      const bit = (val >> index) & 1;
      const toggleBit = bit ^ 1;

      if (node.children[toggleBit] && node.children[toggleBit].count > 0) {
        node = node.children[toggleBit];
        result |= 1 << index;
      } else {
        node = node.children[bit];
      }
    }

    return result;
  }
}

Released under the MIT license