• 1483. 树节点的第 K 个祖先 折半/倍增


    1483. 树节点的第 K 个祖先

    给你一棵树,树上有 n 个节点,按从 0 到 n-1 编号。树以父节点数组的形式给出,其中 parent[i] 是节点 i 的父节点。树的根节点是编号为 0 的节点。

    树节点的第 k 个祖先节点是从该节点到根节点路径上的第 k 个节点。

    实现 TreeAncestor 类:

    • TreeAncestor(int n, int[] parent) 对树和父数组中的节点数初始化对象。
    • getKthAncestor(int node, int k) 返回节点 node 的第 k 个祖先节点。如果不存在这样的祖先节点,返回 -1 。

    示例 1:

    输入:
    ["TreeAncestor","getKthAncestor","getKthAncestor","getKthAncestor"]
    [[7,[-1,0,0,1,1,2,2]],[3,1],[5,2],[6,3]]
    
    输出:
    [null,1,0,-1]
    
    解释:
    TreeAncestor treeAncestor = new TreeAncestor(7, [-1, 0, 0, 1, 1, 2, 2]);
    
    treeAncestor.getKthAncestor(3, 1);  // 返回 1 ,它是 3 的父节点
    treeAncestor.getKthAncestor(5, 2);  // 返回 0 ,它是 5 的祖父节点
    treeAncestor.getKthAncestor(6, 3);  // 返回 -1 因为不存在满足要求的祖先节点
    

    提示:

    • 1 <= k <= n <= 5 * 1e4
    • parent[0] == -1 表示编号为 0 的节点是根节点。
    • 对于所有的 0 < i < n ,0 <= parent[i] < n 总成立
    • 0 <= node < n
    • 至多查询 5 * 1e4 次

    来源:力扣(LeetCode)
    链接:https://leetcode.cn/problems/kth-ancestor-of-a-tree-node
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

     做题结果

    成功,根据经验想了折半法,倍增是从题解区学到的

    方法1:折半

    1. 大概50000的范围,n方取1e8,存不下

    2. 不存直接找,最坏 n*5e4,时间超

    3. 那可以平均一下,2个0分给内存,2个0分给查找,那么,存前100个k就行了,内存和查找耗时就都变为1e6,一定可以通过

    1. class TreeAncestor {
    2. int n;
    3. int[] parent;
    4. int[] colors;
    5. int[][] parentK;
    6. public TreeAncestor(int n, int[] parent) {
    7. this.n = n;
    8. this.parent = parent;
    9. parentK = new int[n][101];
    10. for(int i = 0; i < n; i++){
    11. Arrays.fill(parentK[i],-1);
    12. }
    13. for(int i = 0; i < n; i++){
    14. for(int curr = i,j = 0; j <= 100&&curr!=-1; j++){
    15. parentK[i][j]=curr;
    16. curr = parent[curr];
    17. }
    18. }
    19. }
    20. public int getKthAncestor(int node, int k) {
    21. if(node == -1) return -1;
    22. if(k>100) return getKthAncestor(parentK[node][100],k-100);
    23. return parentK[node][k];
    24. }
    25. }

    方法2:倍增(新学)

    参考:力扣在逐渐把 ACM 模板题搬上来,这个问题是 Binary Lifting

    假设k=3,那么k=2e0+2e1,也就是可以通过两个二进制求和得到,那么对于任意一个 int 类型的k,都可以将它分为2进制次数相加。也就是平均分到 17个格子里,分别代表一个二进制数位即可实现在logn时间内找到所有的k

    1. 默认-1,0层是自己,1层是parent[i]

    2. 对于dp[i][j]=dp[dp[i][j-1]][j],也就是走4步等于走2步再走2步,j代表走 (1<

    3. 查找,分解二进制的每一位向前搜索,比如10=2e3+2e2

    1. class TreeAncestor {
    2. int n;
    3. int[] colors;
    4. int[][] parentK;
    5. public TreeAncestor(int n, int[] parent) {
    6. this.n = n;
    7. parentK = new int[n][18];
    8. for(int i = 0; i < n;i++){
    9. Arrays.fill(parentK[i],-1);
    10. }
    11. for(int i = 0; i < n; i++){
    12. parentK[i][0] = i;
    13. parentK[i][1] = parent[i];
    14. }
    15. for(int j = 2; j < 17; j++){
    16. for(int i = 0; i < n; i++){
    17. parentK[i][j] = parentK[Math.max(parentK[i][j-1],0)][j-1];
    18. }
    19. }
    20. }
    21. public int getKthAncestor(int node, int k) {
    22. for(int i = 0; i < 18&&node!=-1; i++){
    23. if(((1<0){
    24. node = parentK[node][i+1];
    25. }
    26. }
    27. return node;
    28. }
    29. }

  • 相关阅读:
    再获数千万元追加投资!宏景智驾B轮总融资已近「5亿元」
    C#操作MySQL从入门到精通(9)——Mysql中的数据类型以及对应的C#中的数据类型
    基于梯度的黑盒迁移对抗攻击(附代码)
    原生实现.NET 5.0+ 自定义日志
    docker 配置 gpu版pytorch环境--部署缺陷检测--Anomalib
    亚马逊哪些因素会影响转化率,如何才能做得更好(测评)
    简单阐述函数
    CentOS上安装Docker
    js中的设计模式之享元模式
    【AcWing16】【LeetCode】并查集Union Find-128/130/*1020-学完广度优先/深度优先要回来再看
  • 原文地址:https://blog.csdn.net/yu_duan_hun/article/details/126592489