【问题标题】:How can I count the time complexity of this recursive function? (BST)如何计算这个递归函数的时间复杂度? (英国夏令时)
【发布时间】:2018-10-29 08:29:01
【问题描述】:

我在计算为我的任务编写的函数的时间复杂度时遇到了一些麻烦。

这个函数是递归的,它计算二叉搜索树中有多少个值大于 10 的叶子。这是函数:

int count_leaf(node* root)
{
  static int count = 0; 
  int call; 
  if (root == NULL) 
   {
     return 0;
   }
  call = count_leaf(root->left);
  if (root->left == NULL && root->right == NULL && root->data > 10)
   {
     count++;
   }
  call = count_leaf(root->right); 
  return count;
}

计算这个函数的时间复杂度的最正确和正确的方法是什么?

【问题讨论】:

  • 所以它正在遍历所有节点,对吧?有多少个节点?
  • 嗯,树中有多少节点有关系吗?据我所知,计算时间复杂度是无用的信息,但是好吧,假设是 33。
  • 假设您知道处理特定树需要多长时间。如果您再向该树添加一个节点,您预计需要多长时间?
  • 如果您尝试多次调用您的函数,您的实现将被破坏。
  • 在具体的任务中 a 不需要多次调用它。但是如果是的话,我可以把这个计数器定义为一个全局变量,并且每次在函数调用之前将它初始化为零

标签: c recursion tree binary


【解决方案1】:

复杂度实际上是O(n),因为您需要访问所有节点。这比与二叉树关联的O(n*log n) 更好。它也是渐近最优的。

子节点直接从父节点访问,而不是从根节点,以此类推,以这种方式访问​​子节点是一个常数时间操作。遍历完成后,所有n 节点都已被访问。

【讨论】:

    【解决方案2】:

    通过实验衡量算法实现复杂性的一种简单方法是将计数器放在用于迭代的函数或循环的开头。对于您的示例,如下所示:

    int test_count = 0;
    
    int count_leaf(node* root)
    {
      static int count = 0; 
      int call; 
    
      ++test_count;
    
      // ...
    
    }
    

    然后在运行测试后打印出test_count 的值。如果您使用不同的测试集进行实验(使每个集的大小是前一个的两倍以使差异明显),您将很好地指示算法是否为 O(1)、O(n)、O(n^ 2)等。

    另一种方法是使用简单的计时器来测量测试运行的持续时间。将运行算法的时间与几个大小翻倍的数据集进行比较。处理每个数据集的时间差异将为您提供算法计算复杂性的指示。有关示例,请参见 Sedgewick 的“算法”第 4 版第 1.4 节。

    显然,这些不是证明,对于大多数家庭作业的答案可能是不可接受的 - 但它可以帮助您确保您得到了正确的家庭作业答案。

    【讨论】:

    • 几个问题:像你一样在变量名之前标记增量是否重要?以及如何在不使用静态或全局计数器的情况下实现此功能?我看不到以另一种方式解决它的正确方法:(
    • 由于增量评估不用作较大表达式的一部分,因此增量类型的详细信息并不重要。 test_count++test_count += 1test_count = test_count+1 在这里都可以正常工作。我认为如果没有一个全局的计数器,就不会有一种简单、干净的方式来使用计数器。这种方法实际上只是为了实验。
    【解决方案3】:

    它只接触树的每个节点一次,所以会有n调用,变成O(n)

    【讨论】:

    • 谢谢!而且没有办法优化它吗?因为我必须检查每片叶子的值是否大于 10...
    • 其实有....想一想二叉搜索树中的节点是如何排列的。这与他们的价值观有什么关系?
    • 如果您将随着时间的推移对各种值进行多次检查,将计算时间用于从二叉树创建二叉搜索树 (BST) 可能是有意义的。一旦你有一个结构良好(有点平衡)的 BST,每次调用将花费 ~O(logN) 时间而不是 ~O(N)。
    • 恕我直言,这取决于您感兴趣的 什么 时间复杂度 - 最坏的情况?平均?
    • 另一种可能性(您可能不是在寻找,但以防万一......)是缓存您感兴趣的叶子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    相关资源
    最近更新 更多