版权声明:本文为博主原创文章,可以转载,但转载前请联系博主。 https://blog.csdn.net/qq_33528613/article/details/84886988
台阶问题
台阶问题描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
斐波那契数列
0, 1, 1, 2, 3, 5, 8, 13......
递归算法:
def fib_recur0(n):
if 0 <= n <= 1:
return n
else:
return fib_recur0(n-2) + fib_recur0(n-1)
递归算法 - pythonic(不考虑 n 等于 0 的情况):
def fib_recur1(n):
return n if 0<= n <= 1 else fib_recur2(n-1) + fib_recur2(n-2)
递归算法改进 - 使用备忘录缓存
def fib_recur2(n):
global cache
cache = {0:0, 1:1}
if n not in cache.keys():
cache[n] = fib_recur2(n-2) + fib_recur2(n-1)
return cache[n]
递归算法改进 - 使用备忘录缓存 - 使用装饰器
def memo1(func):
cache = {}
def wrapper(arg):
if arg not in cache.keys():
cache[arg] = func(arg)
return cache[arg]
return wrapper
fib_recur1 = memo1(fib_recur1)
递归算法改进 - 使用备忘录缓存 - 使用装饰器 - 改进装饰器
上面的算法中,用装饰器装饰完函数以后,无法正确地获取到原函数的函数名称和帮助信息:
>>> fib_recur1 = memo1(fib_recur1)
>>> fib_recur1.__name__
'wrapper'
为了获取这些信息,我们需要使用@functool.wraps:
from functools import wraps
def memo2(func):
cache = {}
@wraps(func)
def wrapper(arg):
if arg not in cache.keys():
cache[arg] = func(arg)
return cache[arg]
return wrapper
fib_recur1 = memo(fib_recur1)
非递归算法
def fib_iter(n):
first, second = 0, 1
for _ in range(n):
first, second = second, first+second
return first
图解:
测试
def test(func):
lyst = []
for index in range(0, 8):
lyst.append(func(index))
assert lyst == [0,1,1,2,3,5,8,13]
print(func.__name__, 'pass!')
if __name__ == '__main__':
funcs = [fib_recur0, fib_recur1, fib_recur2, memo1(fib_recur1), \
memo2(fib_recur1), fib_iter]
for func in funcs:
test(func)
结果:
$ python3 t.py
fib_recur0 pass!
fib_recur1 pass!
fib_recur2 pass!
wrapper pass!
fib_recur1 pass!
fib_iter pass!
变态台阶问题
变态台阶问题描述
一只青蛙一次可以跳上 1 级、2 级… n 级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
问题分析(数学描述)
将 n 级台阶的跳法记为 f(n)。
n = 1 时,跳法只有 1 种,记为 f(1);
n = 2 时,可以先跳 1 级,然后有 f(1) 种跳法;或者直接跳 2 级,这是 1 种跳法;共计 f(2) = f(1)+1;
n = 3 时,可以先跳 1 级,然后有 f(3-1) 种跳法,即 f(2) 种;或者先跳 2 级,然后有 f(3-2) 种跳法,即 f(1) 种;或者直接跳 3 级;共计 f(3) = f(2) + f(1) + 1 种;
n 级台阶,共有
f(n) = f(n-1) + f(n-2) + … + f(1) + 1 种;
n-1 级台阶,共有
f(n-1) = f(n-2) + … + f(1) + 1 种;
两个等式相减,得到:
f(n) - f(n-1) = f(n-1)
即
f(n) = 2*f(n-1)
递归算法
def f(n):
return n if n <= 1 else 2*f(n-1)
递归算法改进 - 使用备忘录缓存
f = memo1(f)
f = memo2(f)
非递归算法(动态规划)
def g(n):
global d
d = {0:0, 1:1}
for i in range(1, n):
d[i+1] = 2*d[i]
return d[n]
测试
def test(func, arg):
lyst = {}
for i in range(arg+1):
lyst[i] = func(i)
assert lyst == {0:0, 1:1, 2:2, 3:4, 4:8, 5:16}
print('Function ' + func.__name__ + '\'s testcases pass!')
if __name__ == '__main__':
funcs = [f, g, memo1(f), memo2(f)]
for func in funcs:
test(func, arg=5)
assert f(5) == 16
assert g(5) == 16
结果:
$ python3 t.py
Function f's testcases pass!
Function g's testcases pass!
Function wrapper's testcases pass!
Function f's testcases pass!