【剑指offer学习记录】10-斐波那契数列
题目:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39
n=0时,f(n)=0 n=1时,f(n)=1 n>1时,f(n)=f(n-1)+f(n-2)
题目解析
斐波那契数列是一道经典的递归解法的题目。
此题有两种思路,一种是正常的递归方法,但是会产生很多的冗余项,会有很多重复计算项;
因此第二种思路就是按照斐波那契数列的递归计算的状态树,从下往上根据小项来推大项,这样每一项只用计算一次,这种方法代码实现上体现为循环。
代码实现
1 #方法一:递归法 2 class Solution: 3 def Fibonacci(self,n): 4 if n<=0: 5 return 0 6 else n==1: 7 return 1 8 return self.Fibonacci(n-1) + self.Fibonacci(n-2) 9 10 # 方法二:自下而上的循环方法 11 class Solution: 12 def Fibonacci(self, n): 13 res = [0,1] 14 if n<2: 15 return res[n] 16 MinusOne = 1 17 MinusTwo = 0 18 Nsum = 0 19 for i in range(2, n+1): 20 Nsum = MinusOne + MinusTwo 21 MinusTwo = MinusOne 22 MinusOne = Nsum 23 return Nsum
拓展题目一:跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
题目解析
遇到这种有多个状态,而求得结果是多个固定状态组合的结果,都可以考虑递归方法。
在此题中,可以把n级台阶的跳法看做函数f(n)。
第一个状态是跳一阶,剩余n-1,则此时的跳法有f(n-1)种,依赖于后n-1个台阶的跳法
第二个状态是跳二阶,剩余n-2,则此时的跳法有f(n-2)种,依赖于后n-2个台阶的跳法
所以f(n) = f(n-1) + f(n-2)
代码实现
1 class Solution: 2 def JumpFloor(self, number): 3 if number == 1: 4 return 1 5 if number == 2: 6 return 2 7 small, big = 1,2 8 #这里要注意,因为是跳台阶,到第n的时候是不会动的,所以不包含n,和斐波那契数列求和是不同的 9 for i in range(2, number): 10 sum_i = small + big 11 small = big 12 big = sum_i 13 return sum_i
拓展题目二:跳台阶进阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
解题方法
对于此类状态很多的情况,也是先将所有的状态列出来。
首先是f(n)情况,f(n) = f(n-1) + f(n-2) + ... +f(1) + f(0)
再看f(n-1)情况,f(n-1) = f(n-2) + f(n-3) + f(n-4) + ... + f(1) + f(0)
将f(n) - f(n-1),有f(n) - f(n-1) = f(n-1),所以有f(n) = f(n-1),其中n>0,f(1) = 1
所以可以归纳到f(n) = 2^ (n-1)
代码实现
对应的实现有两种,一种是f(n) = f(n-1),一种是直接使用得到的公式f(n) = 2^ (n-1)
1 class Solution: 2 def Jump1(self, number): 3 if number<=0: 4 return 0 5 return 2**(number-1) 6 def Jump2(self, number): 7 if number<=0: 8 return 0 9 if number == 1: 10 return 1 11 return 2*self.Jump(number - 1)
10-扩展题目三:矩形覆盖
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法?
题目解析
此题依旧是斐波那契数列解题的思路,首先根据某一状态进行具体分析,然后找到状态的递推规律。
首先假设是2*8的矩阵,那么可以将单元矩形竖着一列放一个,则剩余部分为2*7的矩阵。
如果是将单元矩阵横着放,则要横着放两个,然后剩余部分为2*6矩阵。
根据这种转换状态,可以知道,f(8) = f(7) +f(6)
代码实现
1 class Solution: 2 def rectCover(self, number): 3 if number<=0: 4 return 0 5 if number == 1: 6 return 1 7 if number == 2: 8 return 2 9 small, big = 1, 2 10 #注意这里到f(n)的话也是要求解的,因为对于n的情况也要覆盖,所以要包含n,因此边界是n+1不包含 11 for i in range(3, number + 1): 12 sum_i = small + big 13 small = big 14 big = sum_i 15 return big