![机器学习入门: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=1739316854-DRlc47pkxMxdM1C7Y4hJRFqLZTIKHYiI-0-b7b20a720910b10006cf94760f27fe08)
阶乘公式的简洁定义如下所示:
![053-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-03.jpg?sign=1739316854-U12XxviepyYrCbyJqLfWgBuYOD8SOyum-0-c1c5ad5d0c72be0160ea217c08110cbd)
清单2.17的Factorial.py
说明了如何通过递归计算一个正整数的阶乘。
清单2.17 Factorial.py
![053-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-04.jpg?sign=1739316854-dXwG3ThgMAbr1EoVjD42Dg32aE62Wq4f-0-8f90932027b20e746c5071b690b8c66a)
清单2.17包含一个函数factorial
,它实现用递归方式计算一个数字的阶乘值。清单2.17的输出如下所示:
![053-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-05.jpg?sign=1739316854-hcrtwqTtCveAe09TObUP3y3lsdxo6XSF-0-844cecdcbad3ebd044745ec4ef69f63b)
除了递归方式之外,还可以用迭代的方式计算数字的阶乘值。清单2.18的Factorial2.py
说明了如何使用range()
函数来计算一个正整数的阶乘值。
清单2.18 Factorial2.py
![053-06](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-06.jpg?sign=1739316854-Ri9cygD9mEHX3RUbpnnDzOPWLwdiK5pa-0-da3fe2c57dd184e42ca0c23073dfa0a4)
清单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=1739316854-LvXNmmAIsBgYm2xIdsDoKDi4KfJvOTKZ-0-7d0a16f45fbc9f09bcffe5c1bd0d7952)
2.5.2 计算斐波那契数
斐波那契数代表了自然界中一些有趣的模式(比如向日葵模式),它的递归定义如下:
![054-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-02.jpg?sign=1739316854-kgiwBM8nCfI05EQ9CpspSSSt8onZgSXF-0-ac13d4b8b56cc8bf6388d6b927a133a7)
清单2.19的fib.py
说明了如何计算斐波那契数。
清单2.19 fib.py
![054-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-03.jpg?sign=1739316854-tQejofUelAhaXltbhXEXPQqlYa2WsQqy-0-983df2baebeebee0b6f8cd2381e85009)
清单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=1739316854-vs2WBjnmjovgOrAY4HXM7CUEGtaPVY22-0-748505623f049c5f2dcabcfa6b339c04)
2.5.3 计算两个数的最大公约数
两个正整数的最大公约数(GCD)是指可以整除两个数的最大整数。比如:
![054-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-05.jpg?sign=1739316854-gAKep0toyZETIOZNP3eUXOJUoXa9hlzg-0-f0b3cc68807689609b5b23c950501090)
清单2.20通过递归和欧几里得算法来查找两个数的最大公约数。
清单2.20 gcd.py
![054-06](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-06.jpg?sign=1739316854-c3VPKyfUWgnWbb0U7Ldx5Re6Q5rPmWng-0-60177525f6bdeaef6d871a43ac809b97)
清单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=1739316854-0NT3nTKgoxOQwljkS4eMGHTVhuGX0OYz-0-35c8dd26ba828d26773c72d9e3610ea7)
2.5.4 计算两个数的最小公倍数
两个正整数的最小公倍数(LCM)是两个数的倍数的最小整数。比如:
![055-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-02.jpg?sign=1739316854-GvSQ85fgRGaGoravGoZGCARVBvKc1olr-0-158188443b539de48e01a1ad9c609f88)
通常,两个正整数x
和y
,你可以按如下所示计算它们的最小公倍数:
![055-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-03.jpg?sign=1739316854-YLmia6j2eIPpGP5DCAPOtQk0gWmIeifT-0-4f8431774debb2c3cd0314611d0098f6)
清单2.21的代码使用前面定义的gcd()
函数来计算两个正整数的最小公倍数。
清单2.21 lcm.py
![055-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-04.jpg?sign=1739316854-nCb6bPr8sNdA3qx180DcP6Me4xr9y0WL-0-b1b0a6f3877b8007364ae7ec9094351e)
清单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=1739316854-pvow9F0Asd8R5ZpMtahLg9TWSQyzFFl0-0-3f48d20589fa45b2e488ea46fa80429d)