树上倍增模版
详细见灵神题解
代码模版(python)
#n是节点个数,parent是父节点数组
def __init__(self, n: int, parent: List[int]):
m = len(bin(n)[2:])-1 #m表示最多能往上数多少个祖先
#开辟st表数组 p[x][i]表示x节点的2^i个祖先
pa = [[p] + [-1]*m for p in parent]
for i in range(m):
for j in range(n):
p = pa[j][i]
if p!=-1:
#j节点的2^(i+1)个祖先相当于是j的2^i个祖先的2^i个祖先
pa[j][i+1] = pa[p][i]
self.pa = pa
相关题目练习
【leetcode】1483.树节点的第k个祖先
题目描述
数据集范围
思路
对于寻找某一节点的k次祖父节点,显然最暴力的做法就是对于该节点进行k次循环不断往上寻找祖父节点,时间复杂度为O(mn),m为查询次数,这显然对于该题的数据范围是不可取的。考虑到快速幂算法与本题有相似之处,因此可以用倍增的思想来优化时间复杂度。对于某一节点x,记录其向上跳了2^i次后的节点为pa[x][i],很自然的可以得到对于跳了2^(i+1)次之后的节点,即pa[x][i+1]为x节点跳了2^i后得到的节点再跳2^i次得到的节点,即pa[x][i+1]=pa[pa[x][i]][i]。因此我们只需要在开始的时候用O(nlogn)的时间初始化pa数组,即可以在每次查询用O(logk)的时间获取k次祖父节点。因此本题的总时间复杂度从O(mn)优化到了O(nlogn+mlogk)。
代码实现
class TreeAncestor:
def __init__(self, n: int, parent: List[int]):
m = len(bin(n)[2:])-1
pa = [[p] + [-1]*m for p in parent]
for i in range(m):
for j in range(n):
p = pa[j][i]
if p!=-1:
pa[j][i+1] = pa[p][i]
self.pa = pa
def getKthAncestor(self, node: int, k: int) -> int:
bit = str(bin(k)[2:])
deep = 0
for b in bit[::-1]:
if b == '1':
node = self.pa[node][deep]
if node == -1:
break
deep+=1
return node