小规模台阶问题
问题描述
有个高度为10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。要到达最上面问一共有多少种走法?
问题分析
记Step(n)
为到达n
级台阶的走法总数。
因为每跨一步只能向上1级或者2级台阶,所以到达第10层之前,必然先到达第9层或第8层,即:
Step(10) = Step(9) + Step(8)
到达第9层,则必然先到达第8层或第7层,即:
Step(9) = Step(8) + Step(7)
以此类推,到达第3层,则必然先到达第2层或第1层,即:
Step(3) = Step(2) + Step(1)
到达第2层,则必然先到达第1层或直接到达,即:
Step(2) = Step(1) +1
到达第1层,只有一种方法。所以可以得到结果。
golang 代码如下:
func Step(n int) int {
if n <= 0 {
return 0
} else if n == 1 || n == 2 {
return n
} else {
return Step(n-1) + Step(n-2)
}
}
大规模台阶问题
问题描述
有个高度为n
级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。要到达最上面问一共有多少种走法?
问题分析
台阶有n
级,当n
较大时,如果使用递归求解,程序运行时间可能会很长,这时可以用双指针法循环求解。
用两个指针a
,b
,分别记录到达n-2
,n-1
级台阶的方法数。从n=3
开始求解,不断右移a
,b
指针。例如:
当n=3
时,a
,b
记录的是1
,2
级台阶到达的方法数;
当n=4
时,a
,b
记录的是2
,3
级台阶到达的方法数;
…
当n=k
时,a
,b
记录的是k-2
,k-1
级台阶到达的方法数。
golang 代码如下:
func StepLarge(n int) int {
if n <= 0 {
return 0
} else if n == 1 || n == 2 {
return n
} else {
step := 0
// 此时 a,b 指向第1级,第2级
a, b := 1, 2
for i := 3; i <= n; i++ {
step = a + b
// 右移指针
a, b = b, step
}
return step
}
}
斐波那契数列定义
斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89…
这个数列从第3项开始,每一项都等于前两项之和。
递归
// 计算斐波那契数列第n个值
func Fib(n int) int {
if n <= 0 {
return 0
} else if n == 1 {
return 1
} else {
return Fib(n-1) + Fib(n-2)
}
}
非递归
一般来说,如果看到一个算法有多个递归调用,就可以认为它的运行时间是指数级的。
由于上述递归方法的时间复杂度达到指数级,所以当n
很大时,考虑使用非递归方法求解。
// 计算斐波那契数列第n个值
func Fib2(n int) int {
if n <= 0 {
return 0
} else if n == 1 || n == 2 {
return 1
} else {
s := 0
a, b := 1, 1
for i := 2; i < n; i++ {
s = a + b
a, b = b, s
}
return s
}
}