这个问题可能已经被很多人提出过,但是,它有点不同。我们有一棵二叉树。你得到两个节点p& Q值。我们必须找到最不常见的父母。但是你没有指向根的根节点指针。您将获得两个内置函数:
1)BOOL same(node *p, node *q);
- >如果节点相同则返回true,否则返回false。
2)node* parentNode(node *c);
- >返回一个节点,该节点是当前节点的父节点。
如果节点c实际上是root,那么parentNode函数将返回NULL
值。
使用我们必须的函数来找到树的最不常见的父。
答案 0 :(得分:6)
第1步:使用parentNode
函数从根目录中查找节点d1
的距离p
。类似地从根节点找到节点d2
的距离q
。 (例如,d2
出现大于d1
)
第2步:移动更远的节点(其d值更大)指针d2-d1
向根行进。
第3步:同时将指针p
和q
移向root,直到它们指向同一节点并返回该节点。
基本上它就像找到两个链表的合并点。
检查以下链接:
Check if two linked lists merge. If so, where?
时间复杂度:O(N)
您的代码看起来有点像:
node* LCP(node* p, node *q){
int d1=0, d2=0;
for(node* t= p; t; t = parentNode(p), ++d1);
for(node* t= q; t; t = parentNode(q), ++d2);
if(d1>d2){
swap(d1, d2);
swap(p, q);
}
for(int i=0; i<(d2-d1); ++i)
q = parentNode(q);
if( same(p, q)){
return parentNode(p);
}
while( !same(p, q)){
p = parentNode(p);
q = parentNode(q);
}
return p;
}
答案 1 :(得分:1)
假设C ++:
node* leastCommonParent(node *p, node *q)
{
node *pParent = parentNode(p);
while(pParent != 0)
{
node *qParent = parentNode(q);
while(qParent != 0)
{
if (0 == same(pParent, qParent))
return pParent;
qParent = parentNode(qParent);
}
pParent = parentNode(pParent);
}
return 0;
}
更新:使用递归的没有显式声明变量的版本如下。我确信它可以改进,并且可能永远不会在当前形式的生产代码中使用它。
node* qParent(node *p, node *q)
{
if (p == 0 || q == 0)
return 0;
if (same(p, q) == 0)
return p;
return qParent(p, q->parent);
}
node* pParent(node *p, node *q)
{
return qParent(p, q) ? qParent(p, q) : pParent(p->parent, q);
}
node * result = pParent(p, q);