Algorithm 按递归树排序

Algorithm 按递归树排序,algorithm,recursion,Algorithm,Recursion,我曾尝试通过递归关系确定运行时间,但结果不正确 重复性 T(n) = c + T(n-1) if n >= 1 = d if n = 0 我的尝试 我构建了这个递归树: n | n-1 | n-2 | n

我曾尝试通过递归关系确定运行时间,但结果不正确

重复性

T(n) = c + T(n-1) if n >= 1
     = d          if n = 0
我的尝试

我构建了这个递归树:

                   n
                   |
                  n-1
                   |
                  n-2
                   |
                  n-3
                   |
                  n-4
                   |
                  n-5
                   |
                   |
                   |
                   |
                   |
                   |
                Till we get 1
现在在级别
i
,子问题的大小应该是,
n-i

但最后我们需要一个大小为1的问题。因此,在最后一级,
n-i=1
给出了,
i=n-1

因此,树的深度变为
n-1
,高度变为
n-1+1=n

现在,求解此递归所需的时间=树的高度*每个级别所需的时间,即:

n+(n-1)+(n-2)+(n-3)+(n-4)+(n-5)+ ...
==> (n+n+n+n+n+ ... )-(1+2+3+4+5+ ... )
==> n - (n(n+1)/2)
现在所用的时间=n*((n-n2)/2),应该给出n2的顺序,但这不是正确的答案

T(n) = c + T(n-1) 
     = c + (c + T(n-2)) 
     = ... 
     = c*i + T(n-i) 
     = ...
     = c*n + T(0)
     = c*n + d
如果我们假设c,d是常数,它就得到了O(n)

要从数学上证明它,可以使用

对于每个
k
假设
T(n)=c*n+d

基数为
T(0)=0*n+d=d
,这对于n<1是正确的

T(n) = c + T(n-1)               (*)
     = c + (n-1)*c + d 
     = c*n + d
(*)是归纳假设,自n-1 如果我们假设c,d是常数,它就得到了O(n)

要从数学上证明它,可以使用

对于每个
k
假设
T(n)=c*n+d

基数为
T(0)=0*n+d=d
,这对于n<1是正确的

T(n) = c + T(n-1)               (*)
     = c + (n-1)*c + d 
     = c*n + d
(*)是归纳假设,并且是有效的,因为n-1复杂性将是O(n)

如您所述,函数通过使用常量运算“c”将输入n的问题转换为(n-1)的问题

因此,沿着递归树向下移动,我们总共有n个级别,在每个步骤中,我们需要一些常量运算“c”

因此,将有总的c*n操作导致复杂性O(n)。

复杂性将是O(n)

如您所述,函数通过使用常量运算“c”将输入n的问题转换为(n-1)的问题

因此,沿着递归树向下移动,我们总共有n个级别,在每个步骤中,我们需要一些常量运算“c”

因此,将有总的c*n操作导致复杂性O(n)

现在在第一级,子问题的大小应该是,n-i

是的,没错。但您假设运行时等于所有子问题大小之和。试想一下,前两个级别的总和已经给出了
n+(n-1)=2n-1
,为什么问题的规模会增加?免责声明:有点手工,不是完全准确的陈述

公式实际上是怎么说的 公式上说,为一些
n
求解它所需的时间与为一个较小的问题求解它所需的时间相同,再加上一个附加常数
c
c+T(n-1)

另一种表达上述观点的方式是:假设某个问题的大小需要一段时间
t
,那么一个问题的大小需要
t+c
,这个问题的大小要大一倍

我们知道,当问题大小为
n=0
时,这需要时间
d
。根据第二条语句,对于一个以上的大小,
n=1
,需要
d+c
。再次应用我们的规则,因此
n=2
需要
d+c+c
。我们得出结论,任何
n
都必须花费
d+n*c
时间

这不是证据。要真正证明这一点,必须使用amit所示的归纳法

正确的递归树 递归树只列出问题的大小。恐怕那没什么用。相反,您需要列出所述问题大小的运行时

树中的每个节点都对应一个特定的问题大小。您在该节点中写入的内容是问题大小所需的额外时间。也就是说,将一个节点的所有子代加上节点本身求和,以获得某个问题大小的运行时

这种树的图形表示如下所示

Tree        Corresponding problem size
c                                    n
|
c                                    n - 1
|
c                                    n - 2
|
c                                    n - 3
.
.
.
|
c                                    2
|
c                                    1
|
d                                    0
形式化:如前所述,节点的标签是解决该问题所需的额外运行时,以及其所有子代。最上面的节点表示问题大小
n
,带有标签
c
,因为这是对
T(n-1)
的补充,它使用
|
与之连接

在一个公式中,您只需编写以下关系:
T(n)=c+T(n-1)
。给定该树,您可以看到这如何应用于每个
n>=1
。你可以这样写下来:

T(n)     = c + T(n - 1) # This means, `c` plus the previous level
T(n - 1) = c + T(n - 2) # i.e. add the runtime of this one to the one above^
T(n - 2) = c + T(n - 3)
...
T(n - (n - 2)) = c + T(1)
T(n - (n - 1)) = c + T(0)
T(0) = d
现在可以从下至上展开术语:

T(n - (n - 1)) = c + T(0)
T(0) = d

T(n - (n - 2)) = c + T(1)
T(n - (n - 1)) = c + d
T(0) = d

T(n - (n - 3)) = c + T(2)
T(n - (n - 2)) = c + (c + d)
T(n - (n - 1)) = c + d
T(0) = d

T(n - (n - 4)) = c + T(3)
T(n - (n - 3)) = c + (2*c + d)
T(n - (n - 2)) = c + (c + d)

...

T(n) = c + T(n - 1)
T(n - 1) = c + ((n-2)c + d)

T(n) = c + (n-1)c + d = n*c + d
T(n - 1) = (n-1)c + d
求和
1到n
从第一行到第二行,您已将问题从求和
1到n
减少到求和
1到n-1
。这不是很有帮助,因为你遇到了同样的问题

我不确定你在第三行做了什么,但是你从第一行到第二行的转换基本上是正确的

这将是正确的公式:

现在在第一级,子问题的大小应该是,n-i

是的,没错。但您假设运行时等于所有子问题大小之和。试想一下,前两个级别的总和已经给出了
n+(n-1)=2n-1
,为什么问题的规模会增加?免责声明:有点手工,不是完全准确的陈述

公式实际上是怎么说的 公式上说,为一些
n
求解它所需的时间与为一个较小的问题求解它所需的时间相同,再加上一个附加常数
c
c+T(n-1)

另一种表达上述观点的方式是:假设某个问题的大小需要一段时间
t
,那么一个问题的大小需要
t+c
,这个问题的大小要大一倍

我们知道,当问题大小为
n=0
时,这需要时间
d
。雅高
n+(n-1)+(n-2)+(n-3)+(n-4)+(n-5)+ ...
==> (n+n+n+n+n+ ... )-(1+2+3+4+5+ ... )
==> n - (n(n+1)/2)