我在一次职业面试中被问到了这个问题,下面是我的 O(log n)
解决方案。
找到节点的深度。
重复搜索,但在 depth - n
处停止。
有没有办法在不进行第二遍搜索的情况下完成这个问题呢?
我在一次职业面试中被问到了这个问题,下面是我的 O(log n)
解决方案。
找到节点的深度。
重复搜索,但在 depth - n
处停止。
有没有办法在不进行第二遍搜索的情况下完成这个问题呢?
在查找节点时,您可以跟踪从当前节点到根节点的所有节点路径。这是一个简单的列表,长度不大于树的深度。一旦找到节点,它的第n个祖先位于列表中的位置为length - n。
findnth(node *root, queue q, int n, int number)
{
if(!root || !q)
return;
findnth(root->left, q, n, number);
if(root->d == number) {
if(q.size() < n) {
nth ancestor not exist;
print q->deq() as q.size() ance return;
}
else
print q.deq()
}
if(q.size() < n) {
q.ins(node->data);
}
else {
q.deq();q.enq(node->data);
}
findnth(root->right, q, n, number);
}
只需查找节点并在跟随它时保存路径。 大致如下(对于整数树):
Node* nthAncestor(Node* root, int target, int n)
{
Node* list[n];
int pos = 0;
Node* node = root;
while(node->value != target)
{
list[pos] = node;
pos = (pos + 1) % n;
if(node->value < target)
node = node->left;
else if(node->value > target)
node = node->right;
}
return list[(pos + 1) % n];
}
while
后面的分号是有意为之吗? - Gumbo嗯,我想到了一个简单的方法,只需要一个额外的节点或更少的空间,就可以有一个虚拟节点来保存回溯计数。当你找到搜索目标时,你可以将虚拟节点设置为n并返回它,而不是你不想要的找到的节点。
你需要一个函数DUMMY(node)
,它仅对虚拟节点返回true。(DUMMY()
可以通过比较节点地址或检查节点内部的魔术cookie来实现。)
Node *search(Node *next) {
if (found the the answer)
dummy->backtrack = n;
return dummy;
} else r = search(whatever ? n->left : n->right);
if (DUMMY(r)) {
if (dummy->backtrack == 0)
return next;
--dummy->backtrack;
}
return r;
}
你的问题有点错误,我猜测你漏掉了一个重要的事项。当然你可以不用第二次遍历来完成它。只需维护一个队列,包含你搜索的最后n个节点。
你忽略的是这种算法需要O(log n)
的内存。而你的解决方案则是以时间消耗为代价,使用O(1)
(恒定数量)的额外内存。
所以你的解决方案并不是“错误”或“太慢”。它只是有其优缺点。
I think this function might help ...
function printAncestor(node *root , node *search , int *k)
{
if(!root)
return 0;
if(root == search)
return 1;
int p1 ,p2;
p1 = printAncestor(root->left , search , k);
p2 = printAncestor(root->right , search , k);
if(p1) {
(*k)--;
if(*k >0)
printf("%d ",root->left->value);
return 1;
}
if(p2)
{
(*k)--;
if(*k >0)
printf("%d ",root->right->value);
return 1;
}
}
是的,可以在不进行第二次遍历的情况下完成。您只需要使用两个指针即可。以下是如何实现:
n
和树中的项目数量混在一起了。这是有意为之吗? - P Shved