Python算法题----玩转fibonacci数列

fibonacci数列是个很常见的面试题,相信大家都见识过,反正我碰见过两次。递归是最容易想到的办法。但是写一个递归,往往面试官并不满意,会追问。这个递归存在什么问题啊。有没有其它办法啊……。办法总比问题多,跳跳大路通帝都。下面就总结一下。把程序写到面试官的心缝里!

递归法

这个递归存在的最严重的问题就是重复计算,在代码的递归分支里可以看到函数被递归调用了两次,那么很多函数其实都被重复计算了。最后再来解决这个问题。

def fib01(n):
    if n == 1 or n == 2:
        return n
    else:
        return fib01(n-1) + fib01(n-2)

递推法1

使用一个列表来存储整个fibonnci数列,所求的即为列表的第n项

def fib02(n):
    if n == 1 or n == 2:
        return n
    else:
        arr = [1, 1, 2]
        i = 3
        for i in range(3, n+1):
            arr.append(arr[i-1] + arr[i-2])
        return arr[n]

递推法2

声明几个历史变量不断计算数列的值,并且交换变量

def fib03(n):
    if n == 1 or n == 2:
        return n
    else:
        x = 1
        y = 2
        for i in range(3, n+1):
            fi = x + y
            x = y
            y = fi
        return y

缓存递归中间结果

定义一个字典,将递归函数的计算结果存入_fib_cache,每次判断该函数是否在缓存中,在直接返回,不在,计算并放入缓存

_fib_cache = {}
def fib04(n):
    if n in _fib_cache:
        return _fib_cache[n]
    else:
        _fib_cache[n] = n if n <= 2 else fib04(n-1) + fib04(n-2)
        return _fib_cache[n]

有了缓存,生活美好了很多,但是看着有点别扭。孤零零的_fib_cache,弄个装饰器多好,这明显可以有个装饰器的。

函数装饰器

def memo(f):
    cache = {}

    def decorated(*args):
        if args in cache:
            return cache[args]
        else:
            cache[args] = f(*args)
            return cache[args]

    return decorated

有了这个装饰器函数,我们就可以装饰我们的递归函数了

@memo
def fib01(n):
    if n == 1 or n == 2:
        return n
    else:
        return fib01(n-1) + fib01(n-2)
时间: 2024-10-05 23:27:16

Python算法题----玩转fibonacci数列的相关文章

python算法题 python123网站单元四题目

目录 一:二分法求平方根 二:Collatz猜想 三:算24(只考虑满足,不考虑把所有情况找出来) ??下面向大家介绍几个python算法题. 一:二分法求平方根 1.题目要求为 2.输入输出格式为 3.博主解题的思路 ??这道题在c语言中是一道经典的题目,可以用循环,或者递归,在这里我们用python来写.无论是循环还是递归,都是下面的思路: ??二分法就是从中间开始取,把我们每次的结果的变化值(这里是平方)和初始数值对比,然后分别从左右两边截取. ??这里首先设定两个范围定界符low与hig

Python算法题(一)——青蛙跳台阶

题目一(青蛙跳台阶): 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 分析: 假设只有一级台阶,则总共只有一种跳法: 假设有两级台阶,则总共有两种跳法: 假设有n级台阶,那么第一步就要分为跳一步和跳两步: 跳一步,那么接下来就是跳n-1: 跳两步,那么接下来就是跳n-2: 所以,总数可以认为是f(n-1)+f(n-2). 主要代码: def frog(num): if num <= 2: return num t1, t2 = 1, 2 for _

Python算法题----在列表中找到和为s的两个数字

列表data的值为[1, 3, 4, 5, 8, 9, 11],找出这个列表中和为13的两个数字的所有组合.这个好找,上过幼儿园大班的,估计都能找出来.4+9=13, 5+8=13.如何用python写一个函数来实现呢. 解法一: 超级大循环 最容易想到的就是遍历啊.嵌套循环,外层循环遍历全部列表,内层循环遍历当前元素位置之后的所有元素.内层循环中将两个数字相加,等于13就break.妥妥找到. def equalSum01(data=None, twosum=13):     result =

Python算法题----孙悟空吃蟠桃

孙悟空第一天摘下若干蟠桃,当即吃了一半,还不过瘾,又多吃了一个.第二天早上,他又将剩下的蟠桃吃掉了一半,还不过瘾,又多吃了一个.之后每天早上都吃掉前一天剩下的桃子的一半零一个.到第十天早上再想吃时,就只剩下一个蟠桃了.求孙悟空第一天共摘了多少个蟠桃? 此题目利用递推的思想,倒推是一种很直观的做法.第十天是1个,根据题意后一天吃掉前一天的一半零一个.那第九天的蟠桃是第十天的一倍加1个再加上第十天的. 即: x9 = 2 * x10 + 1 + x10 = 2 * x10 + 2 = 4 那好办了.

Python算法题----逆序列表

有这样一个列表[1, 2, 3, 4, 5, 6, 7, 8, 9]编程实现该列表逆序排列,将其变为[9, 8, 7, 6, 5, 4, 3, 2, 1] . 题目有了,看看怎么答,逆序排列,只需要将第一个和倒数第一个,第二个和倒数第二个,一直到中间那个位置的数字依次进行交换即可. 假设列表为data, 列表长度为len(data) [1, 2, 3, 4, 5, 6, 7, 8, 9] 0  1  2  3  4  5  6  7  8 从上图的列表和其下标可得出如下结论: 列表第1个元素下标

Python算法题----Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space. class Solution(object):     def numLen(self, n):         i = 1         while True:             n /= 10             if n > 0:                 i += 1             else:          

Python算法题(二)——国际象棋棋盘(排列组合问题,最小的K个数)

题目一(输出国际象棋棋盘)  分析: 用i控制行,j来控制列,根据i+j的和的变化来控制输出黑方格,还是白方格.   主要代码: for i in range(8): for j in range(8): if (i+j)%2!=0: print(chr(219)*2,end='') else: print(' ',end='') print('') 题目二(排列组合问题)   有1.2.3.4个数字,能组成多少个互不相同且无重复数字的四位数?都是多少?   分析:  我们可以先预测一下,共有2

笔试算法题(11):Josephus环 &amp; Fibonacci序列

出题:Josephus Cycle,约瑟夫环问题.k个数字连成一个环,第一个数字为1.首先从1开始计数删除第m个数字:然后从上次被删除的数字的下一个数字开始计数,删除第m个数字:重复进行第二步直到只剩下一个数字:输出最后剩下的一个数字: 分析: 解法1:考虑到问题的特殊性,可以使用哑元素表示删除的元素从而避免由于删除元素带来的额外操作,所以链表实现的话不用考虑删除操作,数组实现的话不用考虑内存移动操作.当然完全可以不适用哑元素,对于链表而言可以节省查找时间,数组的话需要增加数组元素的平移开销:

【算法导论学习-28】Fibonacci数列及其相关

1.解决方案 Fibonacci数列增长很快,第100个已经到了10的20次方,64位计算机才表示到19次方.所以这里统一采用计算第40个数来比较性能.实际上,4个字节的int类型只能计算到第48个Fibonacci数(以0.1.1.2开头)为1836 311 903,一个18亿左右的数字. 1)递归方法--写法简单,效率非常低下 public class Fibonacci { /** * @param args */ public static void main(String[] args