递归算法
func fibonacciRecursive(_ n: Int) -> Int {
if n <= 1 {
return n
}
return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2)
}
迭代算法
func fibonacciIterative(_ n: Int) -> Int {
if n <= 1 {
return n
}
var a = 0
var b = 1
for _ in 2...n {
let temp = b
b = a + b
a = temp
}
return b
}
递归算法性能较差原因分析
- 函数调用开销:每次递归调用都需要在栈上分配新的栈帧,保存函数的参数、局部变量和返回地址等信息。随着递归深度的增加,栈空间的开销会越来越大。
- 重复计算:递归算法会重复计算很多相同的子问题。例如,计算
fibonacciRecursive(n)
时,会多次计算 fibonacciRecursive(n - 1)
和 fibonacciRecursive(n - 2)
的值,这导致了大量不必要的计算。
- 内存管理:由于大量的栈帧分配,可能会导致栈溢出错误,尤其是在处理较大数据时,栈空间是有限的。
迭代算法性能优化
- 减少变量使用:在迭代算法中,我们只使用了三个变量
a
、b
和 temp
,减少了内存的使用,使得算法更加高效。
- 避免重复计算:迭代算法通过逐步计算每个斐波那契数,避免了递归算法中的重复计算问题,大大提高了计算效率。
避免数据溢出问题
- 使用更大的数据类型:对于较大的
n
,斐波那契数会变得非常大,可能会导致整数溢出。可以使用 Int64
或者 BigInt
类型(如果需要处理极其大的数)。例如:
func fibonacciIterativeLarge(_ n: Int) -> Int64 {
if n <= 1 {
return Int64(n)
}
var a: Int64 = 0
var b: Int64 = 1
for _ in 2...n {
let temp = b
b = a + b
a = temp
}
return b
}
- 取模运算:如果只是关心斐波那契数对某个数的余数,可以在计算过程中不断进行取模运算,防止数据过大。例如:
func fibonacciIterativeMod(_ n: Int, _ mod: Int) -> Int {
if n <= 1 {
return n
}
var a = 0
var b = 1
for _ in 2...n {
let temp = b
b = (a + b) % mod
a = temp
}
return b
}