在给定二叉树中的两个值的情况下找到最不共同的祖先[关闭]

Posted

技术标签:

【中文标题】在给定二叉树中的两个值的情况下找到最不共同的祖先[关闭]【英文标题】:Find least common ancestors given two values in binary tree [closed] 【发布时间】:2012-10-27 23:25:16 【问题描述】:

我在一次编程面试中得到了这个问题。请随意考虑如何回答。

给定一个二叉树(不是二叉搜索树)的根节点,其中每个节点都包含一个整数值,并且没有值出现两次。您还将获得两个值 val1val2(可能在树中也可能不在树中。)如果两者都在树中,则返回包含这两个值的两个节点中最小共同祖先的节点.如果不是,则返回 null。

假设每个节点都可以访问左右子节点。您可以附加节点结构,但您可以将父节点附加到每个节点。您的算法应该在小于 O(N^2) 的时间内运行,其中 N 是树中的节点数。

注意:虽然它类似于著名的最不常见祖先问题,但这个问题的局限性使其不完全相同。

【问题讨论】:

有趣。你的尝试是什么? @MichaelPetrotta 我能够回答这个问题,但我希望其他人有机会考虑一下。这公平吗? 不是真的,不 - 这不是 Stack Overflow 的意义所在。我毫不怀疑有人会回答,但 SO 不是脑筋急转弯的网站。这是一个针对您遇到的问题提出问题的网站(希望您尝试过解决问题,您可以与我们分享)。 或者,您也可以回答自己的问题:blog.***.com/2011/07/… @MichaelPetrotta 嗯..那真的不是我发布这个问题的重点。我只想分享一个可能对其他人有用的有趣问题,并给他们一个思考的机会。如果这违背了 SO 的目的,那么我会让人们注意这个问题。 【参考方案1】:

我不明白你为什么会考虑 O(N2),除非我误解了这个问题。以下解决方案是前序遍历,因此每个节点最多访问一次:

struct node* visit(struct node* visited, int p, int q, struct node* sentinel) 
  if (!visited) return visited;
  if (visited->data == p || visited->data == q) 
    struct node* t;
    if ((t = visit(visited->left, p, q, visited))) return t;
    if ((t = visit(visited->right, p, q, visited))) return t;
    return sentinel;
   else 
    struct node* left = visit(visited->left, p, q, visited);
    struct node* right = visit(visited->right, p, q, visited);
    if (left == visited) return right ? right : sentinel;
    if (right == visited) return left ? left : sentinel;
    return left ? left : right;
  


struct node* lca(struct node* root, int val1, int val2) 
  return visit(root, val1, val2, 0);

我想一些解释是有序的,但也许因为它只是一个脑筋急转弯,最好把代码留在那里,看看人们是怎么理解的。 (而且我也没有彻底测试过,让它看起来更像是一次采访。)

这不是我在采访中使用过的问题,如果有人提出上述代码作为答案,我不确定我会做出什么。但后来我一直不确定自己会雇用自己。

【讨论】:

由于唯一性约束,前两次递归调用visit只能返回null(无匹配)或visited(匹配一次),因此整个块可以简化为return visit(visited->left, p, q, visited) || visit(visited->right, p, q, visited) ? visited : sentinel;跨度> 同样在if (right == visited)的情况下,left此时只能为空,所以你可以只使用return sentinel;(虽然我承认对称看起来不错)。 @Neil,你当然是对的,虽然我不是 100% 相信你的台词是简化的;我怀疑它最终会成为至少一条额外的机器指令。 (取决于您对简化的定义。)FWIW,我最初想到但被删除的表达方式,使用了 GNU ?: 扩展名:return visit(visited->left, p, q, visited) ?: visit(visited->right, p, q, visited) ?: sentinel;,这可能不是该特定扩展名的典型代表。跨度> 很公平,我只是不明白你为什么要费尽心思来保存价值。

以上是关于在给定二叉树中的两个值的情况下找到最不共同的祖先[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何在任何二叉树中找到两个节点的最低共同祖先?

如何在任何二叉树中找到两个节点的最低共同祖先?

寻找二叉树中的最低公共祖先结点----LCA(Lowest Common Ancestor )问题(递归)

在二叉树中查找给定节点的祖先

python代码实现二叉树中最低的公共祖先

236. 二叉树的最近公共祖先[中等]