1 台阶问题 斐波那契
题目说明
经典的面试题:
一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法?
斐波那契除了 GitHub 面试题给的那三种外, 还有我之前实现过的一种, 都整理在这个文件了, 包括:
递归求斐波那契(函数形式)
循环求斐波那契(函数形式)
带记忆的递归求斐波那契(函数形式 + 装饰器)
循环求斐波那契(类形式)
fibonacci.py
#!/bin/env python3
# -*- coding: utf-8 -*-
# version: Python3.X
import timeit
from functools import wraps
__author__ = '__L1n__w@tch'
def recursion(n):
"""
普通的递归求斐波那契
:param n:
:return:
"""
if n <= 2:
return n
else:
return recursion(n - 1) + recursion(n - 2)
def memory(function):
"""
作为修饰器存在的
:param function:
:return:
"""
cache = {}
@wraps(function) # 加这句主要是为了保留被修饰的函数的名字
def wrap(args):
if args not in cache:
cache[args] = function(args)
return cache[args]
return wrap
@memory
def memory_recursion(n):
"""
函数本身依旧是普通的递归求斐波那契, 但是装有修饰器
:param n:
:return:
"""
if n <= 2:
return n
else:
return memory_recursion(n - 1) + memory_recursion(n - 2)
def circle(n):
"""
循环求斐波那契
:param n:
:return:
"""
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return b
class Fibonacci:
"""
自己之前写的一个斐波那契数列
"""
def __init__(self, f0, f1):
self.f0 = f0
self.f1 = f1
def _fib(self, a, b):
a = self.f0
b = self.f1
yield a
yield b
while True:
a, b = b, a + b
yield b
def fib_generator(self):
"""
生成器
:return:
"""
return self._fib(self.f0, self.f1)
if __name__ == "__main__":
print("方法一: 匿名函数(其实就是递归), 注意这种写法被 PEP8 报警了...")
# fibonacci_1 = lambda n: n if n <= 2 else fibonacci_1(n - 1) + fibonacci_1(n - 2)
fibonacci_1 = recursion
time_cost = timeit.timeit("recursion(33)", setup="from fibonacci import recursion", number=1)
print("fibonacci_1(33) 耗时: {}".format(time_cost))
print("方法二: 依旧递归求解, 不过加了个记忆用的修饰器, 速率翻倍了都")
fibonacci_2 = memory_recursion
time_cost = timeit.timeit("memory_recursion(33)", setup="from fibonacci import memory_recursion")
print("fibonacci_2(33) 耗时: {}".format(time_cost))
print("方法三: 循环求解")
fibonacci_3 = circle
time_cost = timeit.timeit("circle(33)", setup="from fibonacci import circle", number=1)
print("fibonacci_3(33) 耗时: {}".format(time_cost))
print("方法四: 同样循环求解, 不过是通过生成器实现的")
fibonacci_4 = Fibonacci(1, 2).fib_generator()
单元测试
本文件是对同文件夹下的 fibonacci 几种写法进行测试
#!/bin/env python3
# -*- coding: utf-8 -*-
# version: Python3.X
import unittest
from fibonacci import recursion, memory_recursion, circle
__author__ = '__L1n__w@tch'
class FibonacciTest(unittest.TestCase):
def setUp(self):
self.wait_to_test = [recursion, memory_recursion, circle] # 待测试的函数
def normal_test(self):
"""
简单的功能性测试罢了
:return:
"""
for function in self.wait_to_test:
self.failUnless(function(1) == 1)
self.failUnless(function(2) == 2)
self.failUnless(function(3) == 3)
self.failUnless(function(4) == 5)
self.failUnless(function(5) == 8)
self.failUnless(function(6) == 13)
self.failUnless(function(7) == 21)
self.failUnless(function(13) == 377)
self.failUnless(function(15) == 987)
self.failUnless(function(20) == 10946)
self.failUnless(function(25) == 121393)
self.failUnless(function(29) == 832040)
self.failUnless(function(33) == 5702887)
if function.__name__ == "recursion":
print("递归 50 次时间太长, 不测试了")
continue
self.failUnless(function(50) == 20365011074)
print("函数: {}, 测试完毕".format(function.__name__))
if __name__ == "__main__":
unittest.main()
Last updated
Was this helpful?