美文网首页
动态规划例题

动态规划例题

作者: 多问Why | 来源:发表于2020-06-10 17:03 被阅读0次

动态规划就是把一个复杂的问题分拆为几个小问题,一步步求解。

  1. 求最长连续增长子序列。

给出一个数列,输出最长连续增长序列个数。比如[1,2,3,8,5,7,0,4,2] 输出结果为4,即序列[1,2,3,8]。只要输出个数就行,不用输出子序列。
这个问题就比较复杂,第一不知道子序列从哪个数开始,第二也不知道子序列在哪个数结束。只有知道开始结束后才能求出其长度。
(1)不知道子序列以哪个数结尾那就把以每个元素结尾的最长连续增长序列长度都算出来,再找出最大值便可。
(2)现在已知序列的结尾,要找也开头了,但其实不用管开头是什么,因为只要求出序列的长度就可以了。所以只要看前面一个数比当前数字大还是小就可以了。比如以7结尾的序列,前面一个数5比7小,所以以7结尾的比以5结尾的序列大1。否则只能是自己一个数,长度为1.比如以0结尾的最长连续增长子序列就是[0].
(3) 求出以每个元素结尾的最长连续增长子序列后找出最大的即可。


nums = [1,2,3,8,5,7,0,4,2]

def endLength(index):
    if index == 0:
        return 1
    current_num = nums[index]
    if current_num > nums[index -1]:
        return endLength(index -1) + 1
    else:
        return 1

result_list = []
for i in range(len(nums)):
    result = endLength(i)
    result_list.append(result)

max_length = max(result_list)
print(max_length)

这样可以得出结果,但用了递归。由于求后面一个数要利用前一个数的结果,每次重新计算导致时间复杂度增加。因此可以将结果保存下来加以利用。

def max_inc_length(arr):
    if not arr:
        return 0
    length_list = [1] * len(arr)
    for i in range(1, len(arr)):
        if arr[i] > arr[i-1]:
            length_list[i] = length_list[i-1] + 1
    return max(length_list)

无论以哪个数结尾的最长连续增长序列其长度至少是1,所以先统一初始化为1,然后它比前一个数大则在其结果上加1,否则就是1,不用做更改。

  1. 求最长增长序列
    这个与上一题类似,只是不要求子序列是连续的。这样的话知道子序列的结尾,那么前一个数就有可能是在它之前所有比它小的数。比如[1, 2, 3, 8, 5, 7, 0, 4, 2, 9, 4, 5]以7结尾的最长增长序列倒数第二个数可能是它之前的5,或3,或2,或1。所以假设每个在它之前比它小的数都为子序列倒数第二个数,找出最大的哪个。
def max_inc_length(arr):
    if not arr:
        return 0
    length_list = [1] * len(arr)
    for i in range(1, len(arr)):
        for j in range(i):
            if arr[i] > arr[j]:
                length_list[i] = max(length_list[j] + 1, length_list[i])
    return max(length_list)
  1. 最少钱币找零
    有1元,5元,8元的钱币,需要找零y元,求最少用几张钱币。
    一种思路是先用8元的凑,剩余金额小于8元时用5元最后用一元,但在这不适用。比如11元,按上需思路要用1张8元3张1元共4张,实际用2张5元和1张1元只需要3张。
    要凑够11元肯定要先凑够10元,6元或3元,然后再加1张就是11元了。所以问题就成了凑够10元,6元或3元最少用几张了,这样就把一个凑较大金额的问题变成了3个凑较小金额的问题,依此类推便可求解。
def min_note_number(amount):
    amount = int(amount)
    if amount <= 0:
        return 0
    if amount == 1:
        return 1
    if amount >= 8:
        return 1 + min(min_note_number(amount-8),min_note_number(amount-5),min_note_number(amount-1))
    if amount >= 5:
        return 1 + min(min_note_number(amount-5),min_note_number(amount-1))
    else:
        return amount

上面还可以优化一下,最小钱币金额是1时,只要金额大于等于第二大金额的钱币就肯定不会只用到1元的。

def min_note_number(amount):
    amount = int(amount)
    if amount <= 0:
        return 0
    if amount == 1:
        return 1
    if amount >= 8:
        return 1 + min(min_note_number(amount-8),min_note_number(amount-5))
    if amount >= 5:
        return 1 + min_note_number(amount-5)
    else:
        return amount

相关文章

  • 动态规划例题

    动态规划就是把一个复杂的问题分拆为几个小问题,一步步求解。 求最长连续增长子序列。 给出一个数列,输出最长连续增长...

  • 动态规划例题

    最优二分搜索树 二分搜索树 是一棵空树 具有下列性质的二叉树若左子树不空,则左子树上所有结点的值均小于它的根结点的...

  • 动态规划例题总结

    一、01背包问题 题目描述:有n个重量和价值分别为wi,vi的物品,从这些物品中挑选出总重量不超过W的物品,求所有...

  • 动态规划问题

    动态规划一般思路 动态规划的条件 无后效性 具备最优子结构 经典例题 思考过程 判断是否满足dp解题的条件; 确定...

  • 剪绳子动态规划例题(java)

    给你一根长度为n的绳子,请把绳子剪成整数长度的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0]...

  • 背包问题

    介绍 学习动态规划算法的经典例题。动态规划算法一般有3个特征1、最优化原理:最优解所包含的子问题的解也是最优的。2...

  • 呕心之作,一篇博客带你精通五大核心算法

    目录 一、分治法 思想原理 具体步骤 例题1 算法结语 二、动态规划算法 思想原理 具体步骤 算法实现 算法结语 ...

  • 最长公共子序列

    动态规划合集: 1.矩阵链乘法2.投资组合问题3.完全背包问题4.01背包问题5.最长公共子序列 例题5——最长公...

  • 矩阵链的乘法问题

    动态规划合集: 1.矩阵链乘法2.投资组合问题3.完全背包问题4.01背包问题5.最长公共子序列 例题1——矩阵链...

  • 投资组合问题

    动态规划合集: 1.矩阵链乘法2.投资组合问题3.完全背包问题4.01背包问题5.最长公共子序列 例题2——投资问...

网友评论

      本文标题:动态规划例题

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