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 * 1e4parent[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. 大概50000的范围,n方取1e8,存不下
2. 不存直接找,最坏 n*5e4,时间超
3. 那可以平均一下,2个0分给内存,2个0分给查找,那么,存前100个k就行了,内存和查找耗时就都变为1e6,一定可以通过
- class TreeAncestor {
- int n;
- int[] parent;
- int[] colors;
- int[][] parentK;
- public TreeAncestor(int n, int[] parent) {
- this.n = n;
- this.parent = parent;
- parentK = new int[n][101];
- for(int i = 0; i < n; i++){
- Arrays.fill(parentK[i],-1);
- }
-
- for(int i = 0; i < n; i++){
- for(int curr = i,j = 0; j <= 100&&curr!=-1; j++){
- parentK[i][j]=curr;
- curr = parent[curr];
- }
- }
-
- }
-
- public int getKthAncestor(int node, int k) {
- if(node == -1) return -1;
- if(k>100) return getKthAncestor(parentK[node][100],k-100);
- return parentK[node][k];
- }
- }
参考:力扣在逐渐把 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