zoukankan      html  css  js  c++  java
  • 动态规划案例之python实现(一)

    本文参考文章:
    《漫画:什么是动态规划?(整合版)》 https://mp.weixin.qq.com/s/3h9iqU4rdH3EIy5m6AzXsg

    题1: 爬楼梯: https://leetcode-cn.com/problems/climbing-stairs/

    假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
    每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
    注意:给定 n 是一个正整数。

    示例 1:

    输入: 2
    输出: 2
    解释: 有两种方法可以爬到楼顶。

    1. 1 阶 + 1 阶
    2. 2 阶
      示例 2:

    输入: 3
    输出: 3
    解释: 有三种方法可以爬到楼顶。

    1. 1 阶 + 1 阶 + 1 阶
    2. 1 阶 + 2 阶
    3. 2 阶 + 1 阶

    原文章主要借由 2 个问题 来讲述什么是动态规划,由浅到深,本篇主要围绕第1个问题,使用python 实现(文中使用java实现)。
    第2个问题放在下一篇实现。

    # 针对试题一 的解法
    # 最优解 斐波拉契数列
    
    class Solution(object):
        def climbStairs(self, n):
            """
            :type n: int
            :rtype: int
            时间复杂度: O(2^n)  ; 这是一颗二叉树,树的高度 n-1 ,节点有 2^(n-1)
            空间复杂度: O(2^n) ; 因为每个计算结果都要存储,而且涉及重复计算
            """
            assert isinstance(n,int),"n 不是整型,请确认后重新输入"
            assert (n > 0), "n 必须大于0,请确认后重新输入"
            if n <= 1:
                return 1
            elif n == 2:
                return 2
            return self.climbStairs(n-1)+self.climbStairs(n-2)
    
        def climbStairs2(self, n, record=dict()):
            """
            :type n: int
            :rtype: int
            备忘录算法,通过一个缓存,来减少重复计算
            时间复杂度: O(n) ; f1~fn 除去 1,2 确定,其他都有走一遍,即 n-2
            空间复杂度: O(n) ; 同理
            """
            assert isinstance(n,int),"n 不是整型,请确认后重新输入"
            assert (n > 0), "n 必须大于0,请确认后重新输入"
            if n <= 1:
                return 1
            if n == 2:
                return 2
            if record.keys().__contains__(n):
                return record.get(n)
            else:
                res = self.climbStairs2(n-1,record)+self.climbStairs2(n-2,record)
                record[n]= res
                return res
    
        def climbStairs3(self, n):
            """
            :type n: int
            :rtype: int
            减少空间复杂度,自底向上
            时间复杂度: O(n)  ; f1~fn 除去 1,2 确定,其他都有走一遍,即 n-2
            空间复杂度: O(1)  ; 因为每个计算结果都要存储两个变量
            """
            assert isinstance(n,int),"n 不是整型,请确认后重新输入"
            assert (n > 0), "n 必须大于0,请确认后重新输入"
    
            if n == 1:
                return 1
            elif n == 2:
                return 2
            a,b,temp = (1,2,0)
            for i in range(3,n+1):
                temp = a+b
                a = b
                b = temp
    
            return temp
    
    
    if __name__ == '__main__':
        s = Solution()
        # res = s.climbStairs(4)
        # res = s.climbStairs2(4)
        res = s.climbStairs3(4)
        print(res)
    
    

    思路: climbStairs函数 是原始解法,但时间及空间复杂度均很大 O(2^n), 考虑到有重复计算,
    所以加个缓存备忘录 字典record, 没有的加进去,后续再遇到就直接从record中取值,没必要再递归到最底层得到结果。即 climbStairs2 函数
    再进一步考虑优化 空间复杂度,自底向上,每次只保留最近的两个结果,即 climbStairs3 函数

    <人追求理想之时,便是坠入孤独之际.> By 史泰龙
  • 相关阅读:
    自己写的jQuery放大镜插件效果(一)(采用一张大图和一张小图片的思路)
    javascript 节点操作拷贝节点cloneNode()
    javascript节点操作移出节点removeChild()
    写的一个封拆包代码
    C#_socket拆包_封包_模拟乱序包
    VS2010使用DX报错 VS报错之混合模式程序集是针对“v1.1.4322”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。
    C#_C++_SDK_WM_KEYDOWN人物卡顿延迟解决方法
    MYSQL游标的使用
    MYSQL异常和错误机制
    CRM中的一个函数,保存一下,别系统被ぅ崩坏就麻烦了.
  • 原文地址:https://www.cnblogs.com/jason-Gan/p/13303601.html
Copyright © 2011-2022 走看看