算法6:c++实现动态规划

1、我们拿 斐波那契数来说,斐波那契数的定义为f(n)=f(n-1)+f(n-2)。我们有以下的方法进行计算,分别是暴力递归,记忆性递归,和动态规划
2、暴力递归方法(缺点是这个方法一定n比较大的时候容易造成时间复杂度很高):
 
class solution
{
public:
    int fbnq(int n)
    {
        if (n == 0)
        {
            return 0;
        }
        if (n == 1)
        {
            return 1;
        }
        else
        {
            return fbnq(n - 1) + fbnq(n - 2);
        }
    }
};

  

3、记忆性递归方法(实际上是通过增加空间复杂度来减少时间复杂度的方法,增加一个记忆来记录数据的方法)
 
class solution
{
public:
    int fbnq(int n, vector<int> arr)
    {
        if (n == 0)
        {
          
            return 0;
        }
        if (n == 1)
        {
            
            return 1;
        }
        if (arr[n] != 0)
        {
            return arr[n];
        }
        else
        {
            return fbnq(n - 1,arr) + fbnq(n - 2,arr);
        }
    }
    int fbnqresult(int a)
    {
        vector<int> f(a+1,0);
        return fbnq(a,f);
    }
    
};

 

这种方法在力扣上面仍然还是超时的,因为虽然减少了时间复杂度,但是还是不满足力扣对时间的要求
4、动态规划(这方法是时间复杂度要求最好的算法之一)
 
class Solution {
public:
    int fib(int n) {
        if(n==0)
        {
            return 0;
        }
        vector<int> f(n+1,0);
        f[1]=1;
        for(int i=2;i<n+1;i++)//动态记录的过程
        {
            f[i]=(f[i-1]+f[i-2]);
        }
        return f[n];
    }
};

 

 
 
3、动态规划三步走:
动态规划,无非就是利用历史记录,来避免我们的重复计算。而这些历史记录,我们得需要一些变量来保存,一般是用一维数组或者二维数组来保存。下面我们先来讲下做动态规划题很重要的三个步骤,
如果你听不懂,也没关系,下面会有很多例题讲解,估计你就懂了。之所以不配合例题来讲这些步骤,也是为了怕你们脑袋乱了
第一步骤:定义数组元素的含义,上面说了,我们会用一个数组,来保存历史数组,假设用一维数组 dp[] 吧。这个时候有一个非常非常重要的点,就是规定你这个数组元素的含义,例如你的 dp[i] 是代表什么意思?
(这里很重要的一个步骤是一般都是从后往前推到的)第二步骤:找出数组元素之间的关系式,我觉得动态规划,还是有一点类似于我们高中学习时的归纳法的,当我们要计算 dp[n] 时,是可以利用 dp[n-1],dp[n-2]…..dp[1],来推出 dp[n] 的,也就是可以利用历史数据来推出新的元素值,所以我们要找出数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2],这个就是他们的关系式了。而这一步,也是最难的一步,后面我会讲几种类型的题来说。
学过动态规划的可能都经常听到最优子结构,把大的问题拆分成小的问题,说时候,最开始的时候,我是对最优子结构一梦懵逼的。估计你们也听多了,所以这一次,我将换一种形式来讲,不再是各种子问题,各种最优子结构。所以大佬可别喷我再乱讲,因为我说了,这是我自己平时做题的套路。
第三步骤:找出初始值。学过数学归纳法的都知道,虽然我们知道了数组元素之间的关系式,例如 dp[n] = dp[n-1] + dp[n-2],我们可以通过 dp[n-1] 和 dp[n-2] 来计算 dp[n],但是,我们得知道初始值啊,例如一直推下去的话,会由 dp[3] = dp[2] + dp[1]。而 dp[2] 和 dp[1] 是不能再分解的了,所以我们必须要能够直接获得 dp[2] 和 dp[1] 的值,而这,就是所谓的初始值。
由了初始值,并且有了数组元素之间的关系式,那么我们就可以得到 dp[n] 的值了,而 dp[n] 的含义是由你来定义的,你想求什么,就定义它是什么,这样,这道题也就解出来了。
 
posted @ 2022-09-04 09:27  铜锣湾陈昊男  阅读(29)  评论(0)    收藏  举报