1483. 树节点的第 K 个祖先
大约 3 分钟
--- 
1483. 树节点的第 K 个祖先
- 标签:树、深度优先搜索、广度优先搜索、设计、二分查找、动态规划
- 难度:困难
题目链接
题目大意
描述:给定一棵 个节点的树(节点编号 ),给定 数组, 表示节点 的父节点(根节点的 为 )。
实现 TreeAncestor 类,支持:
TreeAncestor(n, parent)初始化。getKthAncestor(node, k)返回第 个祖先节点。如果不存在,返回 。
说明:
- 。
- 最多调用 次。
示例:
- 示例 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 因为不存在满足要求的祖先节点- 示例 2:
输入:
输出:解题思路
思路 1:树上倍增
1. 核心思想
预处理每个节点的 级祖先。 表示节点 的第 个祖先。
- (直接父节点)。
- (先跳 步,再跳 步)。
查询 级祖先:将 的二进制分解,对应跳 步。
2. 具体步骤
初始化:
- (,取 或 )。
- 。
- 设置 。
- 递推填充 。
:
- 遍历 :
- 如果 的第 位是 :。
- 如果 :返回 。
- 返回 。
3. 举例说明
以 为例:
0
/ \
1 2
/ \ / \
3 4 5 6表初始化:
递推
查询 getKthAncestor(5, 3):
- ,遍历
- , 第 位为 :
- , 第 位为 :
返回 (节点 只有 级祖先,即 ,没有 级祖先)。
思路 1:代码
class TreeAncestor:
def __init__(self, n: int, parent: List[int]):
LOG = (n).bit_length() # 2^LOG >= n
self.up = [[-1] * LOG for _ in range(n)]
for v in range(n):
self.up[v][0] = parent[v]
for j in range(1, LOG):
for v in range(n):
if self.up[v][j - 1] != -1:
self.up[v][j] = self.up[self.up[v][j - 1]][j - 1]
self.LOG = LOG
def getKthAncestor(self, node: int, k: int) -> int:
for j in range(self.LOG):
if k & (1 << j):
node = self.up[node][j]
if node == -1:
return -1
return node思路 1:复杂度分析
- 时间复杂度:初始化 ,单次查询 。
- 空间复杂度:。