Python实现斐波那契数列与跳台阶变体

本篇记录了斐波那契数列的Python实现:递归与循环两种解法,以及一些化用的题目。

Python实现

递归

按传统的递归方式,简洁、优雅。写出来却是 O ( n 2 ) O(n^2) O(n2)的算法

def fibo(n):
	"""肥波那契函数"""
    if n < 3:
    	return 1
    else:
        return fibo(n-1) + fibo(n-2)

O ( n ) O(n) O(n)的算法

上面“简洁”的算法其实重复算了好多项。比如算fibo(6),它就算了三个fibo(3)、五个fibo(2)。从理论上分析,只要不多算,那就是 O ( n ) O(n) O(n)的算法——大约是算了n次fibo(n-1) + fibo(n-2)

思路也很简洁:构建一个循环,在每次循环中,都有两个变量储存下一次循环的fibo(n-1)fibo(n-2)。当然,循环开始和终止的边界条件是需要注意的。(拿几个数去试一试就行了)

def fibo(n):
	if n < 3:
		return 1
	frist = 1
	second = 1
	third = 1  # 没有这个会怎样?
	count = 3
	while count <= n:
	    third = second + frist
	    frist = second
	    second = third
	    count += 1
	return third

if __name__ == '__main__':  # 测试
	print(fibo(2))  # 1
    print(fibo(6))  # 8

当然,这个算法也有一个简洁的版本,只是不便于拓展和理解:

def fibo(n):
	"""假设输入值为整数,第1项为零。"""
	first, second = 0, 1
	for i in range(2, n + 1):
		first, second = second, first + second
	return first

变体

跳台阶12

一个台阶总共有n级,如果一次可以跳一级或者两级,求总共有多少种跳法?

  1. 假设存在函数 f f f,使得 f ( n ) f(n) f(n)即为所求;
  2. 当台阶数 n = 0 n=0 n=0 n = 1 n=1 n=1时, f ( n ) = 1 f(n)=1 f(n)=1(没有跳法是为一种跳法);
  3. n > 1 n\gt 1 n>1时, f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n1)+f(n2)

看得出来是斐波那契数列吗?就用上面的算法就行了吗?检验一下,两级台阶的时候,总共2种跳法,写个测试,发现输出是1 != 2。。(好吧,肉眼可见)

def fibo(n):
	"""假设输入值为整数"""
	[...]

def test_two():
    assert fibo(2) == 2  # error,1 != 2

怎么回事?分析得不对吗?原来,函数fibo(n)里的n=1代表第一种情况,而这里的第一种情况是台阶数n = 0。故可把输入改成fibo(n - 1),或者把函数里的参数改一改。

跳台阶123

一个台阶总共有n级,如果一次可以跳一级、两级或者三级,求总共有多少种跳法?

改一下就好,理解不了就先用定义把写个代码:

def result123(n):
	"""假设输入值为整数"""
    if n <= 1: return 1
    elif n == 2: return 2
    elif n == 3: return 4
    frist = 1
    second = 2
    third = 4
    for i in range(4, n + 1):
        result = frist + second + third
        frist = second
        second = third        
        third = result
    return result

if __name__ == '__main__':
    print(result123(2))  # 2
    print(result123(3))  # 4
    print(result123(4))  # 7
    print(result123(5))  # 13

跳台阶23

一个台阶总共有n级,如果一次可以跳两级或者三级,求总共有多少种跳法?

还是差不多,只是要从头分析。可以检验一下:

def result23(n):
	"""假设输入值为整数"""
    if n <= 4: return 1
    elif n <= 6: return 2
    frist = 1  # n = 4
    second = 2  # n = 5
    third = 2  # n = 6
    for i in range(7, n + 1):
        result = frist + second
        frist = second
        second = third        
        third = result
    return result

if __name__ == '__main__':
    print(result23(4))  # 1
    print(result23(6))  # 2
    print(result23(7))  # 3
    print(result23(10))  # 7

跳台阶n

一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求总共有多少种跳法。

还是先分析:
f ( n ) = f ( n − 1 ) + f ( n − 2 ) + ⋯ + f ( 1 ) f ( n − 1 ) = f ( n − 2 ) + f ( n − 3 ) + ⋯ + f ( 1 ) f ( n ) − f ( n − 1 ) = f ( n − 1 ) f ( n ) = 2 f ( n − 1 ) = 2 n − 1 f(n) = f(n-1) + f(n-2) + \dots + f(1)\\f(n-1) = f(n-2) + f(n-3) + \dots + f(1)\\f(n)-f(n-1) = f(n-1)\\ f(n) = 2f(n-1)=2^{n-1} f(n)=f(n1)+f(n2)++f(1)f(n1)=f(n2)+f(n3)++f(1)f(n)f(n1)=f(n1)f(n)=2f(n1)=2n1

求个指数总会吧?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值