两个入门级例题了解动态规划(自用版,python)

来源地址:详解多种动态规划问题,看完必会动态规划

解题四大步:确定定义===》找初始值===》思考关系===》写代码解

例题一:青蛙跳台阶

问题:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
步骤1:确定定义

问总共有多少种跳法,就设置n个台阶级的跳法是dp[n]种

步骤2:找初始值

如果只有1级台阶,那么只有一种跳法,即只能跳一级台阶,dp[1] = 1;如果有两级台阶,可以先跳一级台阶,然后再跳一级台阶,或者直接跳两级台阶。一共有两种跳法,即dp[2] = 2;

那么初始值就设为dp[1] = 1, dp[2] = 2;

步骤3:思考关系

这一步可以用穷举分析法,然后发现规律,列出状态转移方程。

针对这一题,穷举分析如下:

为方便阅读,列了个表可视化

台阶数跳法跳法数
111
211,22
3111,21,123
41111,121,211,22,1125
511111,2111,221,1211,1121,1112,212,1228

看着这个表,其实可以思考一下,将跳法理解为最后一步是跳1级还是跳2级,表可以这么改:

台阶数最后一步跳1级的跳法最后一步跳2级的跳法跳法数
11-1
21122
3111,21123
41111,121,21122,1125
511111,2111,221,1211,11211112,212,1228

然后,可以观察出来这么一个规律,即f(n)=f(n-1)+f(n-2),这就是斐波那契数列咯!本题本质就是求斐波那契数列的变体解问题。

步骤4:写代码解

依据以上的关系等式写代码就好

class Solution:
    def numWays(self, n):
        dp = [0 for i in range(n+1)]
        dp[1] = 1
        dp[2] = 2

        for i in range(3, n+1):
            dp[i] = (dp[i-1] + dp[i-2]) % 1000000007
        return dp[n]

例题二:连续子数组的最大和

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。
【示例】
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]。输出: 6。解释: 连续子数组 [4,-1,2,1] 和最大,为 6。

继续以上的四大步!

步骤1:确定定义 

定义某个子数组的和最大值为max_num,动态规划是自底向上不断循环每一步的最优解来使得全局最优,全局最优解max_num已经有了,再设出每一步的局部最优解dp[i](i为循环这个数组的次数,值为每次循环中求得的最大数组)。

步骤2:找初始值

初始值很好设置,就将第一步的局部最优解和全局最优解设置为数组的第一个数字,即nums[0],毕竟要循环它嘛,后面根据循环不断变更这两个值就行。

步骤3:思考关系

如果在循环的过程中,子数组m加上下一个值n的和小于n,即m+n<n,那此时子数组m成为了n的累赘,这时就让n成为新的子数组,继续循环。 如果子数组m加上下一个值n的和大于n,即m+n>n,就将n加到m中,新的子数组就是m+n,即使n的值可能为负数,因为后面可能会有更大的正数,如果遇到n为负数就停滞不前了,那后面如果存在连续很多个都是正数,就得不到想要的最大值了(其实这里我暂时还没完全理解到,如果有大佬看到,希望可以通俗易懂的讲解一下,万分感谢!)。

然后就可以构造出关系式了,就是每次循环中子数组的和应该怎么取:

dp[i] = max(dp[i-1] + nums[i], nums[i])

步骤四:写代码解
class Solution:
    def max_sumsubarray(self, nums):
        dp = [0 for i in range(len(nums))]
        dp[0] = nums[0]
        max_num = nums[0]

        for i in range(1, len(nums)):
            dp[i] = max(dp[i-1] + nums[i], nums[i])
            max_num = max(max_num, dp[i])
        return max_num


if __name__ == '__main__':
    solution = Solution()
    nums = [-2,1,-3,4,-1,2,1,-5,4]
    num = solution.max_sumsubarray(nums)
    print(num)

我下来再理解一下吧,脑子不太灵光,哈哈哈,这个理解透了再去看看其他更难的动态规划题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值