动态规划案例之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 函数

posted on 2020-07-15 08:52  一剑风徽  阅读(201)  评论(0编辑  收藏  举报

导航