Menu
×
   ❮   
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

一个简单的算法


斐波那契数列

斐波那契数列非常适合用来介绍算法,所以在我们继续之前,这里简要介绍一下斐波那契数列。

斐波那契数列以 13 世纪意大利数学家斐波那契命名。

前两个斐波那契数是 0 和 1,下一个斐波那契数总是前两个数的和,所以我们得到 0、1、1、2、3、5、8、13、21、...

创建斐波那契数列。

{{ msgDone }}
{{ x.dieNmbr }}

本教程将大量使用循环和递归。所以,在我们继续之前,让我们实现三种不同版本的算法来创建斐波那契数列,只是为了简单地了解使用循环编程和使用递归编程之间的区别。


斐波那契数列算法

要生成斐波那契数,我们只需要将前两个斐波那契数加起来即可。

斐波那契数列是演示什么是算法的好方法。我们知道如何找到下一个数字的原理,所以我们可以编写一个算法来创建尽可能多的斐波那契数。

以下是创建前 20 个斐波那契数的算法。

它是如何工作的

  1. 从前两个斐波那契数 0 和 1 开始。
    1. 将前两个数加起来以创建一个新的斐波那契数。
    2. 更新保存前两个数的值。
  2. 重复执行步骤 a 和 b 18 次。

循环与递归

为了展示循环和递归之间的区别,我们将使用三种不同的方法实现查找斐波那契数的解决方案。

  1. 使用 for 循环实现上面的斐波那契算法。
  2. 使用递归实现上面的斐波那契算法。
  3. 使用递归查找第 \(n\) 个斐波那契数。

1. 使用 for 循环实现

在编写程序之前,列出代码必须包含的内容或要执行的操作可能是一个好主意。

  • 两个变量来保存前两个斐波那契数
  • 一个运行 18 次的 for 循环
  • 通过将前两个数加起来创建新的斐波那契数
  • 打印新的斐波那契数
  • 更新保存前两个斐波那契数的变量

使用上面的列表,编写程序更容易。

示例

prev2 = 0
prev1 = 1

print(prev2)
print(prev1)
for fibo in range(18):
    newFibo = prev1 + prev2
    print(newFibo)
    prev2 = prev1
    prev1 = newFibo
运行示例 »

2. 使用递归实现

递归是指函数调用自身。

要实现斐波那契算法,我们需要与上面的代码示例中大多数相同的元素,但我们需要用递归替换 for 循环。

要将 for 循环替换为递归,我们需要将大部分代码封装在函数中,并且需要该函数调用自身以创建新的斐波那契数,只要生成的斐波那契数的数量低于或等于 19。

我们的代码如下所示。

示例

print(0)
print(1)
count = 2

def fibonacci(prev1, prev2):
    global count
    if count <= 19:
        newFibo = prev1 + prev2
        print(newFibo)
        prev2 = prev1
        prev1 = newFibo
        count += 1
        fibonacci(prev1, prev2)
    else:
        return

fibonacci(1,0)
运行示例 »

3. 使用递归查找第 \(n\) 个斐波那契数

要查找第 \(n\) 个斐波那契数,我们可以根据斐波那契数 \(n\) 的数学公式编写代码。

\[F(n) = F(n-1) + F(n-2) \]

这仅仅意味着例如第 10 个斐波那契数是第 9 个和第 8 个斐波那契数的和。

注意:此公式使用的是 0 为基的索引。这意味着要生成第 20 个斐波那契数,我们必须写 \(F(19)\)。

当将此概念与递归一起使用时,我们可以让函数调用自身,只要 \(n\) 小于或等于 1。如果 \(n \le 1\) 则意味着代码执行已到达前两个斐波那契数 1 或 0 之一。

代码如下所示。

示例

def F(n):
    if n <= 1:
        return n
    else:
        return F(n - 1) + F(n - 2)

print(F(19))
运行示例 »

请注意,这种递归方法调用自身两次,而不仅仅是一次。这在程序实际在我们的计算机上如何运行方面会产生巨大的影响。当我们增加所需的斐波那契数时,计算次数将呈爆炸式增长。更准确地说,函数调用的次数将随着我们增加所需的斐波那契数而翻倍。

只需查看 \(F(5)\) 的函数调用次数。

The number of function calls with recursion

为了更好地理解代码,以下是如何递归函数调用返回值,以便 \(F(5)\) 最终返回正确的值。

The returns of the recursive function calls

这里有两点需要注意:函数调用的次数和函数使用相同参数调用的次数。

所以,即使代码很迷人,并且展示了递归是如何工作的,但实际的代码执行速度太慢,效率太低,无法用于创建大型斐波那契数列。


总结

在我们继续之前,让我们看看到目前为止我们看到了什么。

  • 算法可以用不同的方式和不同的编程语言实现。
  • 递归和循环是两种不同的编程技术,可以用来实现算法。

现在是时候转到我们将要介绍的第一个数据结构,数组了。

点击“下一个”按钮继续。


DSA 练习

通过练习测试自己

练习

我们如何使 fibonacci() 函数递归?

print(0)
print(1)
count = 2

def fibonacci(prev1, prev2):
    global count
    if count <= 19:
        newFibo = prev1 + prev2
        print(newFibo)
        prev2 = prev1
        prev1 = newFibo
        count += 1
        (prev1, prev2)
    else:
        return

fibonacci(1,0)

开始练习



×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
[email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
[email protected]

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2024 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.