【问题标题】:How to compute a least common ancestor algorithm's time complexity?如何计算最小公共祖先算法的时间复杂度?
【发布时间】:2014-06-07 12:19:22
【问题描述】:

我看到一篇讲 LCA 算法的文章,代码很简单 http://leetcode.com/2011/07/lowest-common-ancestor-of-a-binary-tree-part-i.html

// Return #nodes that matches P or Q in the subtree.
int countMatchesPQ(Node *root, Node *p, Node *q) {
  if (!root) return 0;
  int matches = countMatchesPQ(root->left, p, q) + countMatchesPQ(root->right, p, q);
  if (root == p || root == q)
    return 1 + matches;
  else
    return matches;
}

Node *LCA(Node *root, Node *p, Node *q) {
  if (!root || !p || !q) return NULL;
  if (root == p || root == q) return root;
  int totalMatches = countMatchesPQ(root->left, p, q);
  if (totalMatches == 1)
    return root;
  else if (totalMatches == 2)
    return LCA(root->left, p, q);
  else /* totalMatches == 0 */
    return LCA(root->right, p, q);
}

但我想知道如何计算算法的时间复杂度,有人可以帮我吗?

【问题讨论】:

  • fwiw:如果您可以预先计算所有节点(在 O(n) 时间内),也可以在 O(1) 中找到最低共同祖先en.wikipedia.org/wiki/…

标签: c++ c algorithm time-complexity least-common-ancestor


【解决方案1】:

LCA 的复杂度是O(h),其中h 是树的高度。树高的上限是O(n),其中n 表示树中的顶点/节点数。

如果你的树是平衡的,(见AVLred black tree)高度是log(n),因此算法的总复杂度是O(log(n))

【讨论】:

  • 您计算了 LCA 的成本。但在他的实现中,OP 在函数 countMatchesPQ 中的每次调用(h 次)中遍历子树。所以总复杂度应该大于h。不是吗?
  • 你是对的。这就是为什么我们有你的答案:)
【解决方案2】:

该算法的最坏情况是节点是兄弟离开节点。

Node *LCA(Node *root, Node *p, Node *q)
{
  for root call countMatchesPQ;
  for(root->left_or_right_child) call countMatchesPQ; /* Recursive call */
  for(root->left_or_right_child->left_or_right_child) call countMatchesPQ;
  ...
  for(parent of leave nodes of p and q) call countMatchesPQ;
}

countMatchesPQ 被调用为height of tree times - 1。让我们将树的高度称为h

现在检查辅助函数的复杂度

int countMatchesPQ(Node *root, Node *p, Node *q) {
  Search p and q in left sub tree recursively
  Search p and q in right sub tree recursively
}

所以这是一个广泛的搜索,最终的复杂性是N,其中N 是树中的节点数。

将两个观察值相加,算法的总复杂度为

O(h * N)

如果树是平衡的,h = log N(RB 树,treap 等) 如果树不平衡,更糟糕的情况h may be up to N

所以N 的复杂度可以表示为

对于平衡二叉树:O(N logN)
更准确地说,是实际的 h(N + N/2 + N/4...) 对于平衡树,因此应该是 2hN
对于不平衡二叉树:O(N2)
要更准确地说,它是实际的 h(N + N-1 + N-2...) 对于平衡树,因此应该是 h x N x (N+1) / 2

所以最坏情况的复杂度是 N2

您的算法不使用任何内存。通过使用一些内存来保存路径,您可以极大地改进您的算法。

【讨论】:

  • 更准确地说,h(N + N/2 + N/4...) 应该是 h * logN 对吧?
  • @bigpotato 对于无限级数 (N + N/2 + N/4...),项的总和为 2N。
猜你喜欢
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 1970-01-01
  • 2021-08-25
  • 2011-04-20
  • 1970-01-01
相关资源
最近更新 更多