JavaInterview JavaInterview
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)

『Java面试+Java学习』
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)
  • 指南
  • 简历

  • Java

  • 面试

  • 算法

  • algorithm
  • leetcode
JavaInterview.cn
2026-02-25
目录

1938. 查询最大基因差Java

文章发布较早,内容可能过时,阅读注意甄别。

# 题目

给你一棵 n 个节点的有根树,节点编号从 0 到 n - 1 。每个节点的编号表示这个节点的 独一无二的基因值 (也就是说节点 x 的基因值为 x)。两个基因值的 基因差 是两者的 异或和 。给你整数数组 parents ,其中 parents[i] 是节点 i 的父节点。如果节点 x 是树的 根 ,那么 parents[x] == -1 。

给你查询数组 queries ,其中 queries[i] = [nodei, vali] 。对于查询 i ,请你找到 vali 和 pi 的 最大基因差 ,其中 pi 是节点 nodei 到根之间的任意节点(包含 nodei 和根节点)。更正式的,你想要最大化 vali XOR pi 。

请你返回数组 ans ,其中 ans[i] 是第 i 个查询的答案。

示例 1:

c1.png 输入:parents = [-1,0,1,1], queries = [[0,2],[3,2],[2,5]] 输出:[2,3,7] 解释:查询数组处理如下: - [0,2]:最大基因差的对应节点为 0 ,基因差为 2 XOR 0 = 2 。 - [3,2]:最大基因差的对应节点为 1 ,基因差为 2 XOR 1 = 3 。 - [2,5]:最大基因差的对应节点为 2 ,基因差为 5 XOR 2 = 7 。

示例 2: c2.png

输入:parents = [3,7,-1,2,0,7,0,2], queries = [[4,6],[1,15],[0,5]]
输出:[6,14,7]
解释:查询数组处理如下:
- [4,6]:最大基因差的对应节点为 0 ,基因差为 6 XOR 0 = 6 。
- [1,15]:最大基因差的对应节点为 1 ,基因差为 15 XOR 1 = 14 。
- [0,5]:最大基因差的对应节点为 2 ,基因差为 5 XOR 2 = 7 。

提示:

  • 2 <= parents.length <= 105
  • 对于每个 不是 根节点的 i ,有 0 <= parents[i] <= parents.length - 1 。
  • parents[root] == -1
  • 1 <= queries.length <= 3 * 104
  • 0 <= nodei <= parents.length - 1
  • 0 <= vali <= 2 * 105

# 思路

dfs

# 解法

class Solution {
   public int[] maxGeneticDifference(int[] parents, int[][] queries) {
        int[] ret = new int[queries.length];
        Map<Integer, List<Integer>> map = new HashMap<>();
        Map<Integer, List<int[]>> map2 = new HashMap<>();
        for (int i = 0; i < parents.length; i++) {
            map.computeIfAbsent(parents[i], v -> new ArrayList<>()).add(i);
        }
        for (int i = 0; i < queries.length; i++) {
            map2.computeIfAbsent(queries[i][0], v -> new ArrayList<>()).add(new int[]{queries[i][1], i});
        }
        root = new Trie01();
        dfs(ret, map.get(-1).get(0), map, map2);
        return ret;
    }
    public void dfs(int[] ret, int p, Map<Integer, List<Integer>> sonMap, Map<Integer, List<int[]>> nodeMap) {
        insert(p);
        for (int[] ints : nodeMap.getOrDefault(p, new ArrayList<>())) {
            int vali = ints[0];
            int index = ints[1];
            ret[index] = query(vali);
        }
        for (Integer np : sonMap.getOrDefault(p, new ArrayList<>())) {
            dfs(ret, np, sonMap, nodeMap);
        }
        delete(p);
    }
    Trie01 root;
    public void insert(int num) {
        int index;
        Trie01 node = root;
        for (int i = 31; i >= 0; i--) {
            index = ((1 << i) & num) == 0 ? 0 : 1;
            if (node.nexts[index] == null) node.nexts[index] = new Trie01();
            node = node.nexts[index];
            node.path++;
        }
    }
    public void delete(int num) {
        int index;
        Trie01 node = root;
        for (int i = 31; i >= 0; i--) {
            index = ((1 << i) & num) == 0 ? 0 : 1;
            node = node.nexts[index];
            node.path--;
        }
    }
    public int query(int num) {
        Trie01 node = root;
        int ret = 0;
        int v;
        for (int i = 31; i >= 0; i--) {
            if (node == null) return -1;
            v = ((1 << i) & num) == 0 ? 0 : 1;
            if (v == 0) { //期望获得为1的值
                if (node.nexts[1] != null && node.nexts[1].path != 0) {
                    node = node.nexts[1];
                    ret = ret * 2 + 1;
                } else {
                    node = node.nexts[0];
                    ret *= 2;
                }
            } else {  //期望获得为0的值
                if (node.nexts[0] != null && node.nexts[0].path != 0) {
                    node = node.nexts[0];
                    ret = ret * 2 + 1;

                } else {
                    node = node.nexts[1];
                    ret *= 2;
                }
            }
        }
        return ret;
    }

}
class Trie01 {
    int path = 0;
    Trie01[] nexts = new Trie01[2];
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

# 总结

  • 分析出几种情况,然后分别对各个情况实现
微信 支付宝
#Java
最近更新
01
1644.测试路径 Java
02-25
02
1888. 使二进制字符串字符交替的最少反转次数 Java
02-25
03
1890. 2020年最后一次登录 Java
02-25
更多文章>
Theme by Vdoing | Copyright © 2019-2026 JavaInterview.cn
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式