【问题标题】:Did I manage to estimate O(n) correctly?我是否设法正确估计了 O(n)?
【发布时间】:2019-08-08 01:43:14
【问题描述】:

请注意:这个问题不是关于算法的最佳实现,也不是关于数据结构。


给定一棵二叉树,需要验证它是bst。 我知道更有效的(O(n))算法,问题不在于它。我正在练习我的大 O 估计技能:

int isBST(struct node* node)  
{  
  if (node == NULL)  
    return(true);  

  if (node->left!=NULL && maxValue(node->left) > node->data)  
    return(false);  

  if (node->right!=NULL && minValue(node->right) < node->data)  
    return(false);  

  if (!isBST(node->left) || !isBST(node->right))  
    return(false);  

  return(true);  
}

..假设 maxValue(...)/minValue(...) 是辅助函数,每个函数都需要 O(n) 来运行。

如果h 是它从根开始到叶子结束的“级别”数。在每个级别,maxValue(...)minValue(...) 都在 (n - 1) / 2^l 范围内调用,其中 l 是当前级别。有h 级别,所以我希望得到类似(n - 1) / 1 + (n - 1) / 2 + (n - 1) / 4 + ... + (n - 1) / 2^h 的东西。所以看起来O(n * h) 是一个正确的上限,是吗?

请验证我的想法。

【问题讨论】:

  • 在一个极端中,链表实际上是一棵最大不平衡的二叉搜索树,并且所有子节点都在一个方向上。所以,验证一个数据结构是否是二叉搜索树并不一定是有意义的事情。
  • @TimBiegeleisen,谢谢。我明白。我对树和操作很好,我唯一泄漏的是好的O(n)递归东西的估计技能。这是我写这个问题的唯一目的。
  • @melpomene,去掉了“高度”以避免混淆。请查看更新。
  • 每个节点调用minvalue()maxvalue()函数,并访问整个子树。所以,复杂度必须> O(N) . [出于演示目的,您可以在这三个函数中添加三个(全局)访问计数器,并使用它]
  • 是(n*n)/2,写成O(N*N)

标签: c algorithm time-complexity binary-search-tree


【解决方案1】:

是的,你是对的。这是正确的上限。在每个级别,您将为 maxValues 进行总体 O(n) 工作。您可以检查this 以获得非常相似的运行时分析(它给出了 O(nlogn),因为 h = logn 假设它很平衡)。使用 h 是一个很好的调用,如果树完全不平衡 (h = O(n)) 那么运行时间将为 O(n^2) 但如果它完全平衡 (h= O(logn)) 你将有 O (nlogn)。

还有一件事,你实际上可以在递归时缓存/计算最大值/最小值,它会给你一个摊销的 O(n) 运行时:

struct helper {
  int min;
  int max;
};

int isBST(struct node* root) {  
  struct helper help;
  return isBST_internal(root, &help);  
}

int isBST_internal(struct node* root, struct helper *min_max) {
  if (!root) return true;

  if (root->left) {
    // Recurse on left
    struct helper left_helper;
    int is_left_BST = isBST_internal(root->left, &left_helper)

    if (!is_left_BST || left_helper.max > root->data)
      return false;

    min_max->min = left_helper.min;
  } else {
    // If no left subtree, the min value should be the current node value
    min_max->min = root->data;
  }

  if (root->right) {
    // recurse on right side
    struct helper right_helper;
    int is_right_BST = isBST_internal(root->right, &right_helper)

    if (!is_right_BST || right_helper.min < root->data)
      return false;

    min_max->max = left_helper.max;
  } else {
    // If no right subtree, the max value should be the current node value
    min_max->max = root->data;
  }

  // If we have not returned yet it means all conditions for BST are satisfied
  // Also, min_max is properly set now.

  return true
}

它可能不是最干净的解决方案,但肯定会在线性时间上运行。有额外的 O(h) 空间损失(将辅助结构保存在函数堆栈上),但无论如何,这样的开销在递归时是正常的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 2011-10-19
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 2014-04-26
    相关资源
    最近更新 更多