动态规划-含示例

在学习动态规划之前,我们首先要知道什么是动态规划?

动态规划与分治方法类似,都是通过组合子问题的解来求解原问题的。再来了解一下什么是分治方法以及两者之间的差别,分治方法将问题划分为互不相交的子问题,递归的求解子问题,再将它们的解组合起来,求出原问题的解。而动态规划与之相反,动态规划应用与子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)。在这种情况下,分治方法就会做许多不必要的工作,它会反复求解那些公共子子问题。而动态规划对于每一个子子问题只求解一次,将其解保存在一个表格里面,从而无需每次求解子子问题时都重新计算,避免了不必要的计算工作。

动态规划的方法一般用来求解最优化问题。这类问题可以有很多可行解,每个解都有一个值。我们希望找到具有最优值的解,我们称这样的解为问题的一个最优解而不是最优解,因为可能有多个解都达到最优值。

解决动态规划问题一般分为四步:

1、定义一个状态,这是一个最优解的结构特征

2、进行状态递推,得到递推公式

3、进行初始化

4、返回结果

我们通过几个例子来演示动态规划的过程

[编程题]斐波那契数列 
热度指数:374145时间限制:1秒空间限制:32768K 
算法知识视频讲解 
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。 
n<=39 
这个题目相信大家都很熟悉: 
在我们学习递归的时候应该都见过:我们先写一个递归版本的。 
代码如下:

class Solution {
public:
    int Fibonacci(int n) {
        if(n<=0)
            return 0;
        if(n == 1 || n == 2)
            return 1;
        return Fibonacci(n-1)+Fibonacci(n-2);
    }
};

这个代码的时间复杂度是2^n,也就是指数递增,如果求一个很大数字的时候,运行就会出错,造成栈溢出。

下面我们用动态规划来求解这个问题:

def fabonacii_fun(n):
    if n <= 0:
        return 0
    if n == 1:
        return 1
    fn1 = 0
    fn2 = 1
    result = 0
    for i in range(2, n + 1):
        result = fn1 + fn2
        fn1 = fn2
        fn2 = result

    return result

if __name__ == "__main__":
    print(fabonacii_fun(6))

可以对这个代码进行优化,将空间复杂度变为O(1) 

[编程题]变态跳台阶 
热度指数:221924时间限制:1秒空间限制:32768K 
算法知识视频讲解 
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
先来看简单分析: 

def jumpfloor_fun(n):
    if n == 0:
        return 1
    if n == 1:
        return 1
    total = 1
    for i in range(2, n +1):
        total = 2 * total
    return total
if __name__ =="__main__":
    print(jumpfloor_fun(3))

è¿éåå¾çæè¿°

def rectCover_fun(n):
    if n== 0:
        return 0
    if n==1:
        return 1
    if n ==2:
        return 2
    fn1 = 1
    fn2 =2
    total = 0
    for i in range(3,n +1):
        total = fn1 + fn2
        fn1 = fn2
        fn2 = total
    return total

print(rectCover_fun(4))

编程题]最大连续数列和 
热度指数:5518时间限制:3秒空间限制:32768K 
算法知识视频讲解 
对于一个有正有负的整数数组,请找出总和最大的连续数列。

给定一个int数组A和数组大小n,请返回最大的连续数列的和。保证n的大小小于等于3000。

测试样例: 
[1,2,3,-6,1] 
返回:6 
分析:

状态:f(i)以array[i]结尾的连续子序列的最大和

状态递推:

f(i) = max(f(i-1) + array[i],array[i])

初始化: f(0) = array[0]

返回结果:max(f)

import numpy as np
def getMaxSum_fun(A,n):
    if n == 0:
        return 0
    f = np.zeros(n)
    f[0] = A[0]
    for i in range(1, n):
        f[i] = max(f[i-1] + A[i], A[i])

    return int(max(f))
if __name__ == "__main__":
    print(getMaxSum_fun([6,-3,7,-15,1,22], 6))

[编程题]word-break

给定字符串s和单词词典.,确定s是否可以分割为一个或多个字典单词的空分序列。 
例如,给定 
s =”leetcode”, 
dict =[“leet”, “code”]. 
返回true,因为“leetcode”可以被分割为“leet code”。 
分析: 

import numpy as np
def workbreak_fun(s, dicts):
    n = len(s)
    if len(s) == 0 or len(dicts) == 0:
        return False
    wordchack = np.zeros(n+1)
    wordchack[0] = True
    for i in range(1, len(s)+1):
        for j in range(0, i):
            if wordchack[j] and s[j:i] in dicts:
                wordchack[i] = True
                break

    return bool(wordchack[n])

strlist = "cars"
dictlist = ["car", "ca", "rs"]
print(workbreak_fun(strlist, dictlist))

[编程题]triangle 

给定一个三角形,从上到下求最小路径和。每一步你可以移动到下面行的相邻数字。 
例如,给定以下三角形 

〔2〕; 
[3,4], 
[6],[5],[7] 
[41,1,3] 

从上到下的最小路径和是11(即2+3+5+1=11)。 
注: 
如果你只能使用O(n)额外的空间来做这一点,其中n是三角形中的总行数。 
分析: 

è¿éåå¾çæè¿°

def minpathtotal_fun(A):
    if len(A) == 0 :
        return 0
    min_sum= A
    for i in range(1, len(A)):
        for j in range(i+1):
            # 在最左边
            if j == 0:
                min_sum[i][j] = min_sum[i-1][j] + A[i][j]
            # 最右边
            elif j == i:
                min_sum[i][j] = min_sum[i - 1][j-1] + A[i][j]
            # 中间
            else:
                min_sum[i][j] = min(min_sum[i - 1][j - 1], min_sum[i - 1][j]) + A[i][j]

    return min(min_sum[len(A) - 1])

num_list = [
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
print(minpathtotal_fun(num_list))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值