【LeetCode】1483. Kth Ancestor of a Tree Node 1483. 树节点的第 K 个祖先

该博客介绍了如何在内存受限的情况下,使用O(NlogN)的存储解决树中节点的祖先查询问题。通过记录每个节点的2的幂次祖先,利用分治策略减少查询时间,实现构造时O(NlogN)和查询时O(QlogN)的时间复杂度。算法通过动态规划优化,避免了暴力遍历导致的超时问题。

1

由于O(N^2)的存储会超内存限制,所以直接记忆化肯定凉了。
只能考虑O(NlogN)的存储,方法就对每个node都记下,它k=1,2,4,8,…时候的k祖先。比如,可以用f[h][node]表示node2**h祖先是谁。

需要注意的是,记这个的时候也得做一些优化,直接暴力遍历还是会超时。原理就是:
node的2h2^h2h距离的祖先就是它2h−12^{h-1}2h1祖先的2h−12^{h-1}2h1祖先,f[h][node] = f[h-1][f[h-1][node]]

然后在query的时候,直接跳到最接近的那个位置h,使得2h<=k<2h+12^h<=k<2^{h+1}2h<=k<2h+1,然后找f[h][node]k−2hk-2^hk2h祖先即可。

时间复杂度:

  • constructor: O(NlogN)O(NlogN)O(NlogN)
  • query: O(QlogN)O(QlogN)O(QlogN)
class TreeAncestor:

    def __init__(self, n: int, parent: List[int]):
        h = floor(log(n, 2))
        self.dist = [parent] + [[-1]*n for _ in range(h)]  # dist[i][j] = getKthAncestor(j, 2**i)
        
        for i in range(1, h+1):
            for j in range(n):
                m = self.dist[i-1][j]
                if m != -1:
                    self.dist[i][j] = self.dist[i-1][m]
        
        # print(self.dist)
            
    
    @lru_cache()
    def getKthAncestor(self, node: int, k: int) -> int:
        if node == -1:
            return -1
        h = floor(log(k, 2))
        if k > 2**h:
            return self.getKthAncestor(self.dist[h][node], k - 2**h)
        return self.dist[h][node]


# Your TreeAncestor object will be instantiated and called as such:
# obj = TreeAncestor(n, parent)
# param_1 = obj.getKthAncestor(node,k)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值