从代码转换为递归关系

时间:2013-07-18 19:59:21

标签: c algorithm analysis computation-theory recurrence

我正在读考试,我遇到了一些我需要解决的问题 - 处理基本案例:

我正在从代码转换为递归关系而不是相反

示例1:

 if(n==1) return 0;

现在这段代码的递归关系是:T(1)= 0

我是怎么做到的? 通过查看n == 1,我们看到这是与值>的比较。 0,这是做某种形式的工作所以我们设置“T(1)”并返回0;没有做任何工作,所以我们说“= 0”

 => T(1) = 0;

示例2:

 if(n==0) return n+1*2;

分析:n == 0表示我们没有做任何工作,所以T(0),但返回n + 1 * 2;正在做的工作是“= 1”

 => T(0) = 1;

我想知道的是,如果这是分析一段代码的正确方法,可以提出一个递归关系基础案例吗?

我不确定这些是我自己出现以消除基本情况的可能性:

Example 3: if(n==m-2) return n-1; //answer: T(1) = 1; ?
Example 4: if(n!=2) return n;     //answer: T(1) = 1; ?
Example 5: if(n/2==0) return 1;   //answer: T(1) = 1; ?
Example 6: if(n<2) return;        //answer: T(1) = 0; ?

1 个答案:

答案 0 :(得分:3)

很难分析代码上下文之外的基本情况,因此如果发布整个函数可能会有所帮助。但是,我认为你的困惑源于T(n)总是代表“工作”的假设。我猜你正在上复杂的课程,你已经了解了递归关系作为表达递归函数复杂性的方法。

T(n)只是一个函数:你插入一个数字n(通常是一个正整数),你得到一个数字T(n)。就像任何其他函数一样,T(n)本身没有任何意义。但是,我们经常使用带有符号T(n)的函数来表示算法在大小为n的输入上运行所需的时间量。这是两个独立的概念; (1)函数T(n)和表示它的各种方法,例如递归关系,以及(2)运行算法所需的操作数。

让我举个例子。

int factorial(n)
{
   if (n > 0)
       return n*factorial(n-1);
   else
       return 1;
}

让我们看看是否可以编写代表代码输出的函数F(n)。好吧,F(n)= n * F(n-1),F(0)= 1。为什么?显然,从代码中,F(0)的结果是1.对于n的任何其他值,结果是F(n)= n * F(n-1)。该递归关系是表达递归函数输出的一种非常方便的方法。当然,我可以很容易地说F(n)= n! (阶乘算子),这也是正确的。这是同一函数的非递归表达式。请注意,我没有说过算法的运行时间或它正在做多少“工作”。我只是在编写代码输出的数学表达式。

处理函数的运行时间有点棘手,因为你必须通过“工作”或“操作”来决定你的意思。假设我们不将“return”计为一个操作,但我们将乘法计算为一个操作,并将条件(if语句)计为一个操作。在这些假设下,我们可以尝试为函数T(n)编写递归关系,该函数描述当输入n被赋予函数时完成了多少工作。 (稍后,我会评论为什么这是一个糟糕的问题。)对于n = 0,我们有一个条件(if语句)和一个返回,没有别的。所以T(0)= 1.对于任何其他n&gt; 0,我们有条件,乘法,然而需要很多操作来计算T(n-1)。所以n的总和是:

T(n) = 1 (conditional) + 1 (multiply) + T(n-1) = 2 + T(n-1),
T(0) = 1.

我们可以写T(n)作为递归关系:T(n)= 2 + T(n-1),T(0)= 1.当然,这也只是函数T(n)= 1 + 2n。我想再次强调,这是两个非常不同的功能。当n是输入时,F(n)描述函数的输出。 T(n)描述了当n是输入时完成了多少工作。

现在,我刚才描述的T(n)在复杂性理论方面是不好的。原因是复杂性理论并不是要描述计算只需要一个整数作为参数的函数需要多少工作。换句话说,我们不是在研究F(n)形式的函数所需的工作。我们想要更通用的东西:在大小为n的输入上执行算法需要做多少工作。例如,MergeSort是一种用于对对象列表进行排序的算法。它需要大约nlog(n)次操作才能在n个项目列表上运行MergeSort。请注意,MergeSort没有对数字n执行任何操作,而是在 size n列表上操作。相反,我们的阶乘函数F(n)不在大小为n的输入上运行:假设n是整数类型,因此它可能是32位或64位或其他东西,无论其值如何。或者你可以挑剔并说它的大小是描述它的最小位数。在任何情况下,n都是输入,而不是输入的大小。

当您回答这些问题时,重要的是要非常清楚它们是否需要一个描述函数的输出的递归关系,或者描述运行的递归关系时间的功能。