求解台阶问题和计算斐波那契数列第n个值

本文探讨了小规模和大规模台阶问题的解决方案,通过递归和非递归方法求解斐波那契数列第n个值。针对大规模台阶问题,提出了双指针法以避免递归导致的长运行时间。同时,分析了斐波那契数列的定义,并指出递归方法在n较大时的效率问题。

小规模台阶问题

问题描述

有个高度为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较大时,如果使用递归求解,程序运行时间可能会很长,这时可以用双指针法循环求解。
用两个指针ab,分别记录到达n-2n-1级台阶的方法数。从n=3开始求解,不断右移ab指针。例如:
n=3时,ab记录的是12级台阶到达的方法数;
n=4时,ab记录的是23级台阶到达的方法数;

n=k时,ab记录的是k-2k-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
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值