在给定二叉树中的两个值的情况下找到最不共同的祖先[关闭]
Posted
技术标签:
【中文标题】在给定二叉树中的两个值的情况下找到最不共同的祖先[关闭]【英文标题】:Find least common ancestors given two values in binary tree [closed] 【发布时间】:2012-10-27 23:25:16 【问题描述】:我在一次编程面试中得到了这个问题。请随意考虑如何回答。
给定一个二叉树(不是二叉搜索树)的根节点,其中每个节点都包含一个整数值,并且没有值出现两次。您还将获得两个值 val1
和 val2
(可能在树中也可能不在树中。)如果两者都在树中,则返回包含这两个值的两个节点中最小共同祖先的节点.如果不是,则返回 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;
,这可能不是该特定扩展名的典型代表。跨度>
很公平,我只是不明白你为什么要费尽心思来保存价值。以上是关于在给定二叉树中的两个值的情况下找到最不共同的祖先[关闭]的主要内容,如果未能解决你的问题,请参考以下文章