美文网首页
对动态规划和递归的理解

对动态规划和递归的理解

作者: 舒小贱 | 来源:发表于2017-11-29 11:52 被阅读0次

动态规划的出身

我们知道,一个可以被数学上递归表示的问题,也可以表示成一个递归算法,在许多情形下对朴素的穷举搜索得到显著的性能改进。
任何数学递归公式都可以直接翻译成递归算法,但是基本现实是,编译器常常不能正确对待递归算法,结果导致递归算法的效率低下。当我们怀疑很可能是这种情况时,我们必须再给编译器提供一些帮助,将递归算法重新写成非递归算法,让后者把那些子问题的答案系统的记录在一个表内,这就是动态规划出现的原因和本质

例子:计算斐波那契数的自然递归程序是非常低效的。
对于递归计算斐波那契数的算法:

func Fib(n int)int{
    if n <= 1{
        return 1
    }
    return Fib(n-1) + Fib(n-2)
}

运行时间T(n)满足T(n)>T(n-1)+T(n-2)。由于T(n)作为斐波那契数满足同样的递归关系并且具有同样的初始条件,因此,事实上T(n)是以斐波那契数相同的速度在增长,从而是指数级的在增长。

其实,计算F(n)所需要的只是F(n-1)和F(n-2),因此我们只需要记录最近算出的那两个斐波那契数。于是就有了下面的算法:

func Fib2(n int)int{
    if n <= 1{
        return 1
    }
    var ind1,ind2 = 1
    res = 0
    for(i:=2;i<=n;i++){
        res = ind1 + ind2
        ind1 = ind2
        ind2 = res
    } 
    return res
}

递归算法如此慢的原因在于:算法模仿了递归。为了计算Fn,存在一个对F(n-1)和F(n-2)的调用。然而,F(n-1)又递归的对F(n-2)和F(n-3)进行调用,我们就发现存在两个重复的F(n-2)调用。如果探试整个算法,那么我们可以发现,F(n-3)被计算了3次,F(n-4)计算了5次,F(n-5)计算了8次。。。。如图:

image.png
从图中可以看到,f4,f3,f2等都被重复计算了好多次。
冗余计算的增长是爆炸性的。如果编译器的递归模拟算法要是能够保留一个预先算出的值的表,而对已经解过的子问题不再进行递归调用,那么这种指数级的爆炸增长就可以避免。

另外一个例子:


image.png

计算此值的结果(递归实现):

func getC(n int) float64 {
    if n == 0 {
        return 0
    }

    res := 0.0
    for i := 1; i < n; i++ {
        res += getC(i)
    }
    return 2.0/float64(n)*res + float64(n)
}

func main() {
    res := getC(3)
    fmt.Println(res)
}

非递归实现(借助了表C):

func getC2(n int) float64 {
    if n <= 0 {
        return 0.0
    }
    c := []float64{0.0}
    sumC := 0.0
    for i := 1; i <= n; i++ {
        sumC = sumC + c[i-1]
        c = append(c, 2.0/float64(i)*sumC+float64(i))
    }
    return c[n]
}

这样时间复杂度就是o(n),大大提高了效率

//运行getC2(3)时得到的结果:
C:\Users\minping\Desktop>go run 1.go
5.666666666666666

下面我们再考虑一个问题:矩阵乘法的顺序安排
设给定四个矩阵A,B,C,D,A的维度是5010,B的维度是1040,C的维度是4030,D的维度是305。计算ABC*D的结果。虽然矩阵乘法运算是不可交换的,但它是可结合的。。。(这个问题回来再看)

最优二叉查找树

另外一个动态规划的例子:考虑

reference

相关文章

  • 对动态规划和递归的理解

    动态规划的出身 我们知道,一个可以被数学上递归表示的问题,也可以表示成一个递归算法,在许多情形下对朴素的穷举搜索得...

  • 数据结构学习笔记——第一章:绪论(下)

    五、动态规划 5.1 什么是动态规划   所谓动态规划,可以理解为先通过递归找出算法的本质,并给出一个初步的解之后...

  • 漫谈递归-746. 使用最小花费爬楼梯

    递归特点:从上到下动态规划特点:从下到上。 递归 动态规划

  • 斐波那契数列

    递归解法 动态规划解法1 动态规划解法2

  • 上台阶问题-递归和动态规划

    上台阶是一个常见的问题,解法主要有递归和利用动态规划,这篇文章简单介绍下递归解法和动态规划,以及对应的代码。递归解...

  • 递归和动态规划

    暴力递归:1.把问题转化为规模最小的同类问题的子问题2.有明确的不需要继续进行递归的条件(base,case)3....

  • 动态规划与递归

    动态规划与递归 从研究虚拟dom的实现中看到动态规划的概念。 斐波那契的例子 动态规划与递归的区别从子问题解决原问...

  • 动态规划问题(Java)

    0. 动态规划分析 0.1 动态规划、递归和贪心算法的区别 动态规划就是利用分治思想和解决冗余的办法来处理问题,所...

  • 8.5 feedforward 多分类

    动态规划好简单的递归。图计算

  • 【算法】动态规划(二)

    前言 上一篇,介绍了动态规划DP的概念,以及暴力递归和动态规划的关系。这一篇,将介绍几道经典的动态规划题 1、台阶...

网友评论

      本文标题:对动态规划和递归的理解

      本文链接:https://www.haomeiwen.com/subject/encubxtx.html