【问题标题】:How to get the minimum ancestor of a node in a binary tree如何获取二叉树中节点的最小祖先
【发布时间】:2020-02-06 07:15:09
【问题描述】:

让 T 成为树

           12
       6        3
   13
1     14   

对于节点 (1),最小祖先是 6。对于节点 (3),最小祖先是 12。我正在尝试编写一个递归解决方案来返回节点的最小祖先。

int MinParent(struct Node *root, struct Node *target) {
    if (root == NULL) {
        return INT_MAX;
    }

    if (root->data == target->data) {
        return INT_MAX;
    }

    int res = root->data;

    if ((MinParent(root->left, target) == INT_MAX) || (MinParent(root->right, target) == INT_MAX)) {
        int res = min(??);

        return ??;
    }

    return res;
}

我能够到达给定目标节点的每个祖先节点,但我不知道如何获得这些节点的最小值。

【问题讨论】:

  • 我会使用深度优先搜索。这样,当您找到所需的节点时,堆栈就会包含该节点的所有祖先。
  • 孩子有指向父母的指针吗?

标签: c algorithm binary-tree


【解决方案1】:

当您遍历树时,请跟踪您在该路径上找到的最小值。这可以通过添加第三个参数(目前找到的最小值)轻松完成。

如果找到目标,则返回最小值。

如果你到达一片叶子,返回INTMAX

int MinParent_(struct Node *node, int target, int min) {
   if (node == NULL)
      return INTMAX;

   if (node->data == target)
      return min;

   if (node->data < min)
      min = node->data;

   int rv = MinParent_(node->left, target, min);
   if (rv != INTMAX)
      return rv;

   return MinParent_(node->right, target, min);
}

int MinParent(struct Node *root, int target) {
   return MinParent_(root, target, INTMAX);
}

这使用了一个哨兵值。这意味着数据不能包含INTMAX。我们可以使用指向具有最小值的节点的指针而不是最小值本身来消除该限制。

struct Node *MinParent_(struct Node *node, int target, struct Node *min_node) {
   if (node == NULL)
      return NULL;

   if (node->data == target)
      return min_node;

   if (!min_node || node->data < min_node->data)
      min_node = node;

   struct Node *rv = MinParent_(node->left, target, min_node);
   if (rv)
      return rv;

   return MinParent_(node->right, target, min_node);
}

struct Node *MinParent(struct Node *root, int target) {
   return MinParent_(root, target, NULL);
}

【讨论】:

  • If you reach a leaf, return INTMAX 好计划。 if (node == NULL) return min; 可疑的实现。
  • @graybeard,已修复。 (这只是我们希望问题包含问题的最小可运行演示的原因之一。没有它,我们就无法正确测试。)
【解决方案2】:

您可以通过执行 BFS(或 DFS,并不重要)来解决它,并且每个节点应该携带所有祖先的最小值。例如:

               3(3)
           5(3)    6(3)
        2(3)
     1(2)  4(2)

为了存储所有节点的答案,让我们创建一个映射minimumAncestor

给定一个节点u,计算以u为根的子树中所有节点的所有最小祖先的算法是:

DFS(u, minimumInAncestors){
    minimumAncestor[u] = minimumInAncestors;
    foreach child v of u:
        DFS(v, min(u, minimumInAncestors));
}

要填写地图,请致电DFS(root, root)

通过这样做,映射minimumAncestor[u] 应该在 DFS 的末尾返回任何节点 u 的右最小祖先(根除外,其最小祖先是它自己)。

【讨论】:

  • 应该注意的是,这种方法在 O(N) 遍历成本之上增加了 O(N) 内存成本来映射整个树 - 但这可能是摊销的,但我们不知道与 N 相比,有多少查找。在这一点上,最好以相同的 O(N) 内存成本存储父指针,但是从 targetroot 的遍历变成 O(log N)。鉴于这提供的灵活性,它可能是一种更通用的方法。访问和修改模式现在很重要,因为缓存停顿是真实的。在一个简单的实现中,log N 每次查找都会产生额外的停顿。
猜你喜欢
  • 1970-01-01
  • 2021-09-07
  • 2011-07-28
  • 2012-11-08
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
相关资源
最近更新 更多