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 史泰龙
  • 相关阅读:
    poj 3621(最优比率环)
    bzoj 1497(最大权闭合子图)
    Dinic(模板 再错是不可能的 这辈子都不可能了)
    BZOJ 2038
    zoj 3822(概率dp)
    poj 3683(2-sat+拓扑排序)
    poj 2186(tarjan+缩点)
    hdu 5782(kmp+hash)
    hdu 6035(树形dp)
    Python爬取房屋租售信息
  • 原文地址:https://www.cnblogs.com/jason-Gan/p/13303601.html
Copyright © 2011-2022 走看看