*leetcode刷题(剑指offer9)_(DP)_斐波那契数列

在这里插入图片描述
斐波那契数列 本身就是一个递归的过程(动态规划的问题)
如果求第n个数时,返回的参数是n-1以及n-2。
普通的递归写法:

 def count(self,n):#when we use recursion, we may use one result too many times, which leads to a high complexity
        if n ==0:
            return 0
        if n == 1:
            return 1
        else:
            return self.count(n-1)+self.count(n-2)

咋一看是没问题的,但是测试发现,当n偏向很大的时候,产生了太多的重复过程。比如n-3在n-2以及n-1的求解过程中都有用到。然后它再调用前面的时候也会重复调用,这样对于初始的0 和 1,可能会产生相当大的调用情况。我们在递归时 也要做到尽量避免重复!

这时候可以想到的想法就是 正向迭代,得到最终结果,这样每个参数都只用到了两次。

代码:

def count2(self,n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    else:
        res1 = 1
        res2 = 0
        while n>1:
            res1,res2 = res1+res2,res1
            n-=1
        return res1

回溯就是一种带重复的递归!(正常的递归依然可能会产生重复的情况)
正向迭代一般不会产生多余的过程,但是对于很多情况,正向迭代很难找到需要的target,或者找不到停止的边界点。(例如上一篇中的掷骰子,可以试试正向迭代的情况,其递归情况就会产生重复操作

递归的改进:
同样可以参考上一篇的内容。做一个字典,存储已经产生的结果。存在则直接调用,不存在则添加进去。

改进后的递归代码:

def count0(self, n):
    temp = {}

    def count3(n):  # when we use recursion, we may use one result too many times, which leads to a high complexity
        if n == 0:
            temp[0] = 0
            return 0
        if n == 1:
            temp[1] = 1
            return 1
        else:
            if n - 1 in temp:
                a = temp[n - 1]
            else:
                a = count3(n - 1)
                temp[n-1] = a

            if n - 2 in temp:
                b = temp[n - 2]
            else:
                b = count3(n - 2)
                temp[n-2] = b

            return a + b

    return count3(n)

完整的代码以及测试方式如下:

import time
def singleton(func):
    def count_time(*args):
        a = time.time()
        res = func(*args)
        b =time.time()
        print('time',b-a)
        return res
    return count_time

class Solution:
    #@singleton
    def count(self,n):#when we use recursion, we may use one result too many times, which leads to a high complexity
        if n ==0:
            return 0
        if n == 1:
            return 1
        else:
            return self.count(n-1)+self.count(n-2)

    @singleton
    def count2(self,n):
        if n == 0:
            return 0
        if n == 1:
            return 1
        else:
            res1 = 1
            res2 = 0
            while n>1:
                res1,res2 = res1+res2,res1
                n-=1
            return res1

    def count0(self, n):
        temp = {}

        def count3(n):  # when we use recursion, we may use one result too many times, which leads to a high complexity
            if n == 0:
                temp[0] = 0
                return 0
            if n == 1:
                temp[1] = 1
                return 1
            else:
                if n - 1 in temp:
                    a = temp[n - 1]
                else:
                    a = count3(n - 1)
                    temp[n-1] = a

                if n - 2 in temp:
                    b = temp[n - 2]
                else:
                    b = count3(n - 2)
                    temp[n-2] = b

                return a + b

        return count3(n)




su = Solution()
a = time.time()
res1 = su.count0(30)
b = time.time()
print('time', b - a)
print(res1)###normal recursion

res2 = su.count2(100)
print(res2)###iteration

a = time.time()
res3 = su.count(30)
b = time.time()
print('time', b - a)
print(res3)##improved recursion

tips:
重要的想法:
避免重复!!!在循环的过程中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值