剑指offer笔记9:斐波那契数列(Python)

剑指offer笔记9:斐波那契数列(P74)

目录

  • 剑指offer笔记9:斐波那契数列(P74)
    • 题目一:斐波那契数列
      • 问题分析
      • python代码
        • 方法一(递归)
        • 方法二(迭代)
    • 题目二:青蛙跳台阶问题
      • python代码
    • 题目三:矩形覆盖
      • python代码

题目一:斐波那契数列

输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,n<=39)。斐波那契数列的定义如下:
f ( n ) = { 0 n=0 1 n=1 f ( n − 1 ) + f ( n − 2 ) n>1 f(n)= \begin{cases} 0& \text{n=0}\\ 1& \text{n=1}\\ f(n-1)+f(n-2)& \text{n>1} \end{cases} f(n)=01f(n1)+f(n2)n=0n=1n>1

问题分析

对于递归问题,首先画出递归树,以求f(10)为例:
剑指offer笔记9:斐波那契数列(Python)_第1张图片发现在递归时有很多重复操作,那么对递归树进行剪枝:
剑指offer笔记9:斐波那契数列(Python)_第2张图片把剪枝过后的递归树变化一下:
剑指offer笔记9:斐波那契数列(Python)_第3张图片方法一(递归):用递归的方法,自顶向下的计算,将每次计算结果记录下来,避免每次的重复计算。

方法二(迭代):用迭代的方法,自底向上的计算,只保留前两次的计算结果。时间复杂度O(n),空间复杂度O(1)。

这里的做法参考了labuladong的算法小抄-动态规划解题套路框架里的内容

python代码

方法一(递归)

    def Fibonacci(self, n):
        if n < 1:
            return 0
        # 用列表存储计算结果,对应的结果存在对应索引位置
        # 如:results[5] = f(5)
        # 初始化将结果列表所有值设为0
        results = [0 for _ in range(n+1)]
        # 调用递归方法来求解
        return self.recursion(results, n)

    def recursion(self, results, n):
        if n == 1 or n == 2:
            return 1
        if results[n] != 0:
            # 若已有结果存在,则直接返回该结果
            return results[n]
        # 若当前f(n)没有计算过,则根据公式计算其结果
        results[n] = self.recursion(results, n-1) \
                    + self.recursion(results, n-1)
        return results[n]

方法二(迭代)

    def Fibonacci(self, n):
        if n < 1:
            return 0
        if n == 1 or n == 2:
            return 1
        # 用fn_1来存f(n-1)的值
        fn_1 = 1
        # 用fn_2来存f(n-2)的值
        fn_2 = 1
        # 用fn来存f(n)的值
        fn = fn_1 + fn_2
        for _ in range(3, n+1):
            # 从n=3的时候开始循环,一直循环到n=n
            # 用公式计算f(n)
            fn = fn_1 + fn_2
            # 将f(n-1)和f(n-2)的值进行更新
            fn_2 = fn_1
            fn_1 = fn   
        return fn

题目二:青蛙跳台阶问题

青蛙跳台阶:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
变态跳台阶:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

python代码

    def jumpFloor(self, number):
        # write code here
        if number < 1:
            return 0
        if number == 1:
            return 1
        if number == 2:
            return 2
        fn_1 = 2
        fn_2 = 1
        fn = fn_1 + fn_2
        for _ in range(3, number + 1):
            fn = fn_1 + fn_2
            fn_2 = fn_1
            fn_1 = fn
        return fn
    def jumpFloorII(self, number):
        # write code here
        if number < 1:
            return 0
        return pow(2, number-1)

题目三:矩形覆盖

我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法? *
剑指offer笔记9:斐波那契数列(Python)_第4张图片

python代码

def rectCover(self, number):
        if number < 1:
            return 0
        if number == 1:
            return 1
        if number == 2:
            return 2
        fn_1 = 2
        fn_2 = 1
        fn = fn_1 + fn_2
        for _ in range(3, number+1):
            fn = fn_1 + fn_2
            fn_2 = fn_1
            fn_1 = fn
        return fn

你可能感兴趣的:(剑指offer,python,动态规划,算法,leetcode)