美文网首页
公共祖先问题

公共祖先问题

作者: madao756 | 来源:发表于2020-07-28 00:03 被阅读0次

前言:逃不开的「公共祖先」问题

0X00 一次查询

236. 二叉树的最近公共祖先

用 set 写比较简单,注意其中一个是另外一个祖先的情况。

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', a: 'TreeNode', b: 'TreeNode') -> 'TreeNode':
        parent = {}
        def dfs(r, p):
            if r is None: return
            parent[r] = p
            dfs(r.left, r)
            dfs(r.right, r)

        dfs(root, None)

        p, path = parent[a], set([a])
        while p:
            path.add(p)
            p = parent[p]
        
        if b in path: return b
        p = parent[b]
        while p not in path:
            p = parent[p]
        
        return p

0X01 多次查询

使用「倍增」实现 O(logn) 的查询

首先通过这道题理解「倍增」的思路:

1483. 树节点的第 K 个祖先

class TreeAncestor:

    def __init__(self, n: int, parent: List[int]):
        n = len(parent)
        dp = [[-1] * 20 for _ in range(n)]
        for i in range(n): dp[i][0] = parent[i]
        # 每个点的 i-1 都先做了
        for i in range(1, 20):
            for j in range(n):
                if dp[j][i-1] != -1: dp[j][i] = dp[dp[j][i-1]][i-1]
        self.dp = dp

    def getKthAncestor(self, node: int, k: int) -> int:
        nums = []
        while k:
            nums.append(k % 2)
            k //= 2
        p, dp = node, self.dp
        for i, v in enumerate(nums):
            if v == 0: continue
            p = dp[p][i]
            if p == -1: return -1
        return p

dp[i][j] 表示节点 i 的上面 2^j 个祖先。转移方程为:

dp[i][j] = dp[dp[i][j-1]][j-1] 意思是:节点 i 的上面 2^j 个祖先 等于 节点 i 上面 2^{j-1} 个祖先的 2^{j-1} 个祖先。

最后只需要将 k 以 2 为底分解就能求出答案。

接着通过倍增我们来求 lca

  • 首先我们预处理出深度,将二者深度跳到统一起跑线上
  • 同时向上跳,直到相同

代码如下:

from math import log2
def lca(x, y):
    if dep[x] < dep[y]: return lca(x, y) # 确保 dep[x] > dep[y]
    while dep[x] > dep[y]: x = fa[x][int(log2(dep[x] - dep[y]))] # 保证高度一致
    if x == y: return x # 特判
    for i in range(int(log2(dep[x])), -1, -1): # 一起大步向上跳
        if fa[x][i] != fa[y][i]: x, y = fa[x][i], fa[y][i]
    return fa[x][0]

其中的 fa 就是上面代码的 dp

相关文章

  • 公共祖先问题

    前言:逃不开的「公共祖先」问题 0X00 一次查询 236. 二叉树的最近公共祖先 用 set 写比较简单,注意其...

  • 最近公共祖先

    LeetCode题目地址 在root为根的二叉树中找A,B的LCA: 如果找到了就返回这个LCA 如果只碰到A,就...

  • 最近公共祖先

    最近公共祖先 简称LCA(Lowest Common Ancestor),所谓LCA,是当给定一个有根树T时,对于...

  • 最近公共祖先

    https://www.lintcode.com/problem/lowest-common-ancestor-o...

  • LCA问题及其倍增解法

    [TOC] LCA,最近公共祖先 在有根树中,找出某两个结点u和v最近的公共祖先(或者说,离树根最远的公共祖先)。...

  • LeetCode关于节点公共祖先的问题

    关于我的 Leetcode 题目解答,代码前往 Github:https://github.com/chenxia...

  • IOS 算法(基础篇) ----- 二叉搜索树的最近公共祖先

    又是一道树的问题题目: 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 公共祖先的定义为:“对于有根...

  • 二叉树-最近的公共祖先

    已知二叉树,求二叉树中给定的两个节点的最近公共祖先。 最近公共祖先: 两节点v与w的最近公共祖先u,满足在树上最低...

  • 关于二叉树的最近公共祖先问题

    今天刷题,又遇到了二叉树最近公共祖先问题,发现前段时间写的忘光了,因此决定写下来记录一下。 二叉树最近公共祖先,l...

  • 二叉树的公共祖先

    问题1 平衡二叉树的公共祖先,找到该树中两个指定节点的最近公共祖先 原理 首先需要了解平衡二叉树的特性,平衡二叉树...

网友评论

      本文标题:公共祖先问题

      本文链接:https://www.haomeiwen.com/subject/yyrxrktx.html