Recursion 递归时间复杂性定义混乱

Recursion 递归时间复杂性定义混乱,recursion,time-complexity,Recursion,Time Complexity,递归算法的时间复杂度被称为 Given a recursion algorithm, its time complexity O(T) is typically the product of the number of recursion invocations (denoted as R) and the time complexity of calculation (denoted as O(s)) that incurs along with each recursion O(T)

递归算法的时间复杂度被称为

Given a recursion algorithm, its time complexity O(T) is typically 
the product of the number of recursion invocations (denoted as R) 
and the time complexity of calculation (denoted as O(s)) 
that incurs along with each recursion 
O(T) = R * O(s)
查看递归函数:

void algo(n){
  if (n == 0) return; // base case just to not have stack overflow
  for(i = 0; i < n; i++);// to do O(n) work 
  algo(n/2);
}
void算法(n){
if(n==0)return;//基本情况只是为了避免堆栈溢出
为了(i=0;i
根据上面的定义,我可以说,时间复杂度是,R是logn次,O(s)是n。因此,结果应该是n logn,其中与数学归纳法一样,证明了o(n)中的结果


请不要证明归纳法。我在问为什么给定的定义不适用于我的方法。

我想你是在试图找到有关主定理的信息,主定理是用来证明递归算法的时间复杂性的


此外,通常不能仅仅通过查看来确定算法运行时,尤其是递归算法。这就是为什么你的快速分析不同于归纳证明。

好问题!这涉及到两种不同的方法来计算递归调用链中完成的工作量

您描述的用于计算递归调用中完成的工作量的原始策略(将每个调用完成的工作量乘以调用数)包含一个隐含的假设。也就是说,这假设每个递归调用都做相同的工作量。如果确实如此,那么您可以将完成的总工时确定为调用数和每次调用的工时的乘积

但是,如果每次调用完成的工作量随调用参数的变化而变化,则此策略通常不起作用。毕竟,如果没有一个值表示完成了多少工作,我们就不能谈论将一个调用完成的工作量乘以调用数

确定递归调用链完成的工作量的更一般策略是将每个递归调用完成的工作量相加。对于上面概述的函数,第一次调用完成的工作是n。第二个调用不工作,因为它所做的工作量在其参数中是线性的。第三个调用执行n/4个工作,第四个执行n/8个工作,等等。这意味着完成的总工作以

n+n/2+n/4+n/8+n/16+

=n(1+1/2+1/4+1/8+1/16+…)

≤ 2n

这就是O(n)界更紧的原因

值得注意的是,“将所有调用完成的所有工作相加”的思想完全等同于“将每个调用完成的工作量乘以调用数”,在每个调用完成的工作量相同的特定情况下。你明白为什么吗

或者,如果可以得到递归调用链所完成的工作量的保守上限,则可以将调用数乘以任何一个调用所完成的最大工作量。这永远不会低估总数,但它不会总是给你正确的界限。这就是您所列出的示例中发生的情况-每个调用最多执行n个工作,并且有O(logn)个调用,因此总的工作实际上是O(nlogn)。这并不是一个严格的限制

请注意——我认为将完成的总工作量乘以调用次数的策略称为递归调用链完成的工作量的“定义”是不合适的。如上所述,这更多的是一种“确定完成工作的策略”,而不是一个正式的定义。如果有什么区别的话,我认为正确的形式定义应该是“每个递归调用完成的工作量之和”,因为这更准确地说明了将花费多少总时间

希望这有帮助