算法

1483. 树节点的第 K 个祖先

2023-06-11  本文已影响0人  红树_

LC每日一题,参考1483. 树节点的第 K 个祖先

题目

给你一棵树,树上有 n 个节点,按从 0n-1 编号。树以父节点数组的形式给出,其中 parent[i] 是节点 i 的父节点。树的根节点是编号为 0 的节点。树节点的第 k 个祖先节点是从该节点到根节点路径上的第 k 个节点。
实现 TreeAncestor 类:

输入:["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 因为不存在满足要求的祖先节点

解题思路

倍增+动态规划

class TreeAncestor {
    int[][] ans;
    int M;
    public TreeAncestor(int n, int[] parent) {
        //由于超内存 需要使用倍增表 
        //倍增:第二维j则k=2^j 对于每个k可进行二进制分解为2^k1+2^k2+..
        //比如k=13=1101(2)=2^3+2^2+2^0->找0找2找3的对应父节点
        //确定第二维j最大值
        M = 50000&(-50000);
        //while(Math.pow(2,M) < 50000) M++;
        ans = new int[n+1][M];
        for(int i = 0; i < n; i++) {
            ans[i][0] = parent[i];//k=2^0=1
        }
        //动态规划 2进制两倍关系
        for(int i = 0; i < n; i++) {
            for(int j = 1; j < M; j++) {
                //2^j=2^j-1 + 2^j-1
                if(ans[i][j-1] != -1) ans[i][j] = ans[ans[i][j-1]][j-1];
                else ans[i][j] = -1;
            }
        }
    }
    
    public int getKthAncestor(int node, int k) {
        for(int i = 0; i < M; i++) {
            if(((k>>i)&1) == 1) {
                if(node == -1) return -1;
                node = ans[node][i];
            }
        }
        return node;
    }
}

复杂度分析

上一篇 下一篇

猜你喜欢

热点阅读