【LeetCode】509、斐波那契数列

509、斐波那契数列

一、暴力递归

斐波那契数列,是典型的利用子问题的类型,可用递归实现:

class Solution:
    def fib(self, n: int) -> int:
        if n == 0: return 0
        if n == 1: return 1
        return self.fib(n - 1) + self.fib(n - 2)


if __name__ == '__main__':
    x = Solution().fib(10)
    print(x)

而暴力递归的时间复杂度,即为每次递归操作的时间复杂度 * 递归次数。前者为 O(1),后者为 math.pow(2, N),因此为 O(math.pow(2, N))。

二、带备忘录的递归

而子问题会有很多重复计算,例如下图的 f(18) 就计算了两次:

在这里插入图片描述

为了避免重复计算,可用带备忘录的递归实现,其中 memo 是备忘录,其存储了已计算过的结果,避免重复计算:

class Solution:
    def fib(self, n: int) -> int:
        memo = [0 for i in range(n+1)]
        return self.helper(memo, n)

    def helper(self, memo: list, n: int):
        if n == 0 or n == 1:
            return n
        if memo[n] != 0:
            return memo[n]
        memo[n] = self.helper(memo, n-1) + self.helper(memo, n-2)
        return memo[n]


if __name__ == '__main__':
    x = Solution().fib(4)
    print(x)

2.1 时间复杂度

下图中绿色的 f(18) 和 蓝色的 f(17),均被剪枝了:
在这里插入图片描述

剪枝后,树状即退化成了链表,示例如下:

在这里插入图片描述

而递归的时间复杂度,即为每次递归操作的时间复杂度 * 递归次数。前者为 O(1),后者为 N,因此为 O(N)。

另外有 N(N) 的空间复杂度,来存放 memo 数组。

三、动态规划

然而,上述递归算法本质是先从顶向下调用,再从底向上求解。毕竟 f(20) 需计算 f(19) 和 f(18),而 f(18) 又需计算 f(1) 和 f(0)。

然而,递归有调用栈的开销,我们可完全只用从底向上的方式求解,如已知 f(0) 和 f(1),推导出 f(2), 再推导出 f(3), 最终推导出 f(20),示意图如下:

在这里插入图片描述

class Solution:
    def fib(self, n: int) -> int:
        dp = [0 for i in range(n + 1)]
        dp[0] = 0
        dp[1] = 1  # base case
        for i in range(2, n + 1):
            dp[i] = dp[i - 2] + dp[i - 1]  # 状态转移方程
        return dp[n]


if __name__ == '__main__':
    x = Solution().fib(4)
    print(x)

时间复杂度O(N),空间复杂度O(N)。

3.1 优化空间复杂度

然而每次迭代,并不需要整个 dp 数组,而只需前两个数即可,可优化代码如下:

class Solution:
    def fib(self, n: int) -> int:
        if n < 2: return n
        a, b = 0, 1  # base case
        ans = 0
        for i in range(2, n + 1):
            ans = a + b  # 状态转移方程
            a, b = b, ans
        return ans


if __name__ == '__main__':
    x = Solution().fib(20)
    print(x)

时间复杂度O(N),空间复杂度O(1)。

猜你喜欢

转载自blog.csdn.net/jiaoyangwm/article/details/127473661