看到此题,我们要回忆一下高中数学的排列组合问题
一、先从一个例子分析一下这个题目(‘1’是每次上一级台阶,‘2’是每次上两级提台阶)
假如有5级台阶,则有(1,1,1,1,1)、(1,1,1,2)、(1,2,2)这三种组合方式
其中(1,1,1,1,1)不需要再进行排列
(1,1,1,1,2)如果2的位置不同则是不同的走法,既 =5种组合
(1,2,2)同理,如果2的位置不同则是不同的走法,既 =3种组合
则当 台阶为5的时候有1+5+3=8种走法
二、了解了这个题目后,我们来研究一下这个题的思路
我们需要计算传入参数k中有多少个‘2’,既计算k整除2(k//2),算出来后我们就可以用循环去构建
1个‘2’,(k-2)个‘1’的时候有多少种排列方式
2个‘2’,(k-2*2)个‘1’的时候有多少种组合方式
......
n//2个‘2’,[k-(n//2)*2]个‘1’的时候有多少种组合方式。
列子:
假如传入参数k=7,k中有7//2=3个‘2’。
用循环去构建1个‘2’,5-1*2个‘1’的时候有多少种排列方式;
2个‘2’,7-2*2个‘1’的时候有多少种排列方式;
3个‘2’,7-3*2个‘1’的时候有多少种排列方式。
最后把这三种组合算出来的排列方式加起来再加一次一步一步走的情况就是所有不同种的上台阶方法。
三、推导n个‘1’,m个‘2’时的排列公式、结果
传入台阶数k,则‘2’的个数:m=k//2,‘1’的个数:n=k-2*m
推到出公式m个‘1’,n个‘2’时的走法有种走法
四、代码求解
首先先知道如何用计算机来计算排列
拆分一下公式
假如计算=
,分子每次减少1,分母每次增加1构建循环,代码如下
# 计算排列n为上标,m为下标
def array(n, m):
num = 1 # 初始化
for i in range(1, n + 1):
num *= m / i
m -= 1
return num
通过(三)中的公式计算出每种组合的排列后就很简单了,只需要把每次组合的排列结果加起来再加上一步一步走的情况就能求解出此题了
def how_mach(k=3): # 初始默认值为3
number = 1 # 无论多少阶楼梯都有一步一步走的走法
if k <= 0: # 如果输入为非正数则返回
return False
how_2 = k // 2 # 计算台阶有多少个2; 5个台阶则含有两个2, 6步台阶则含有三个2
for i in range(1, how_2 + 1): # 取多少个2,依次去1个‘2’、2个‘2’一直到how_2个‘2’
# 调用上面的排列函数,用排列计算走法
# 此时的m,n为(三)中的m,n
# array()中第一个参数为公式中的n,第二个参数为公式中的m+n
# i为n; k-2*i为m; 第二个参数m+n = i+k-2*i = k-i
number += array(i, k - i)
return number
五、完整代码
# 计算排列n为上标,m为下标
def array(n, m):
num = 1 # 初始化
for i in range(1, n + 1):
num *= m / i
m -= 1
return num
# 计算走法
def how_mach(k=3): # 初始默认值为3
number = 1 # 无论多少阶楼梯都有一步一步走的走法
if k <= 0: # 如果输入为非正数则返回
return False
how_2 = k // 2 # k中有多少个‘2’
for i in range(1, how_2 + 1):
number += array(i, k - i)
return number
print(how_mach(10))
print(how_mach(5))
print(how_mach(7))
计算结果如下图: