![机器学习入门:Python语言实现](https://wfqqreader-1252317822.image.myqcloud.com/cover/84/41787084/b_41787084.jpg)
2.5 递归
递归是一种强大的技术,可以为各种问题提供优雅的解决方案。下面将介绍几个广为人知的问题,并通过递归来计算它们。
2.5.1 计算阶乘值
一个正整数n的阶乘等于从1到n的所有整数的乘积。阶乘用感叹号(!)来表示,下面是几个数字的阶乘值:
![053-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-02.jpg?sign=1739305883-MU9eNOrX5F7vmoNkztr8m1mafXkSNQ4C-0-752941e1f93e2f98b574507acac5c07e)
阶乘公式的简洁定义如下所示:
![053-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-03.jpg?sign=1739305883-uEXa2Ih37NJQdyA2pKoP9YEay1bct4Y3-0-8c10cf93ad15160841834616be15a896)
清单2.17的Factorial.py
说明了如何通过递归计算一个正整数的阶乘。
清单2.17 Factorial.py
![053-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-04.jpg?sign=1739305883-ReCrMl23CzfzlPJjerUdcFYOPjThYT36-0-77293b1d4acd21d53812e6447d895eb5)
清单2.17包含一个函数factorial
,它实现用递归方式计算一个数字的阶乘值。清单2.17的输出如下所示:
![053-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-05.jpg?sign=1739305883-9yFEGNDdON1HLal86R6voOoZy7Xm02GP-0-b4a95e01eb6fb3c0b5876b4016cd5dd6)
除了递归方式之外,还可以用迭代的方式计算数字的阶乘值。清单2.18的Factorial2.py
说明了如何使用range()
函数来计算一个正整数的阶乘值。
清单2.18 Factorial2.py
![053-06](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-06.jpg?sign=1739305883-10Ry1Y3HqIIkpYFKPzdDhZSvKsAHCPLu-0-97497c0cd1ff7173f07e4c89249c7438)
清单2.18定义一个函数factorial2()
,接受一个形参num
,并初始化变量prod
为1。factorial2()
之后是一个循环变量为x
,并且值为从1
到num+1
的for
循环。循环中的每个迭代用x
的值乘以prod
,由此计算num
的阶乘值。清单2.18的输出如下所示:
![054-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-01.jpg?sign=1739305883-bUpSM9sxEqX5TQuWpV9GbEOgKXCaiCVX-0-1ccaabce28cc69859bebf17c6d105903)
2.5.2 计算斐波那契数
斐波那契数代表了自然界中一些有趣的模式(比如向日葵模式),它的递归定义如下:
![054-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-02.jpg?sign=1739305883-ux9qi7UUzQ77nKd15rnkD4LfYRGNCbWn-0-c00f97fe6065d8d0c9e7ee8b963c4ef0)
清单2.19的fib.py
说明了如何计算斐波那契数。
清单2.19 fib.py
![054-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-03.jpg?sign=1739305883-YWRnNJYVu0DbRRX3MQkd5LTWmVEPTpQH-0-0102c949a909ae7a26b78a48956ee638)
清单2.19的代码定义一个函数fib()
,接受一个形参num
。当num
为0
或1
的时候,fib()
返回num
;否则,fib()
返回fib(num-1)
和fib(num-2)
之和。清单2.19的输出如下所示:
![054-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-04.jpg?sign=1739305883-XZ32yUijKriHDr20jzya3hDBfUG9zHTh-0-1ceafbb9949ab148e189fe29680276a3)
2.5.3 计算两个数的最大公约数
两个正整数的最大公约数(GCD)是指可以整除两个数的最大整数。比如:
![054-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-05.jpg?sign=1739305883-EqwriXfSHhpeTn02eDQ4h3VpNpp1yk65-0-a0a75b4ed972aa48a50931d0e3f277c0)
清单2.20通过递归和欧几里得算法来查找两个数的最大公约数。
清单2.20 gcd.py
![054-06](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-06.jpg?sign=1739305883-FtyO45DYiMkO5t2qamPXkHm0bDjgXhkX-0-f4489692b925f4343a5446df973bffe2)
清单2.20定义一个函数gcd()
,接受两个形参num1
和num2
。如果num1
可以被num2
整除就返回num2
。如果num1
小于num2
,则调换num1
和num2
两个形参的位置调用gcd()
;否则,就用num1-num2
和num2
作为形参调用gcd()
。清单2.20的输出如下所示:
![055-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-01.jpg?sign=1739305883-kMuYFlSefmCsBm3JQ3B43Xm3dktnzuYH-0-16d82bce3f955156b99ceb7f4079cb66)
2.5.4 计算两个数的最小公倍数
两个正整数的最小公倍数(LCM)是两个数的倍数的最小整数。比如:
![055-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-02.jpg?sign=1739305883-plOAgyOPhp9xotMhRjyMAdrPA4JB6pGn-0-26f04d8f7ad95ac819c0fa3d5b5a980b)
通常,两个正整数x
和y
,你可以按如下所示计算它们的最小公倍数:
![055-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-03.jpg?sign=1739305883-egZEPP01hMl43AUvZ3C8x6ty5x8n2o0H-0-5e77475d95c21523442320c7a4d34d21)
清单2.21的代码使用前面定义的gcd()
函数来计算两个正整数的最小公倍数。
清单2.21 lcm.py
![055-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-04.jpg?sign=1739305883-JYUXy97fWOwoCN4E0HiSMVAME991vocu-0-0e07c7328c1a9134d3ce9a2f4ba215ca)
清单2.21先定义一个前面讨论过的gcd()
函数,之后定义一个lcm()
函数接受两个形参num1
和num2
。lcm()
的第一行使用gcd()
计算num1
和num2
的最大公约数gcd1
,第二行计算最小公倍数。最后输出lcm1
的值。清单2.21的输出如下所示:
![056-01](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/056-01.jpg?sign=1739305883-1zKNccxVbEZIWD3kEMTUthHVDUit7mKZ-0-bc88d8b684dae64a58b22bb9ff510329)