![机器学习入门: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=1739897106-H3g57qhn20r1V2sfYlENrezwNQmgeTv8-0-62430d5fb8a6b8298ab86b69b8fbf46d)
阶乘公式的简洁定义如下所示:
![053-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-03.jpg?sign=1739897106-cLbfVYyqmi1yTB9DhO9ToE5fq1xeBdPb-0-2550a1806295e1dc3b42ce1a23f54ae1)
清单2.17的Factorial.py
说明了如何通过递归计算一个正整数的阶乘。
清单2.17 Factorial.py
![053-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-04.jpg?sign=1739897106-9c0PtSJ0ZnfZwsX92ZQOuZurGsqJ2eZw-0-c01a6581c295f6327ad120c924c1d110)
清单2.17包含一个函数factorial
,它实现用递归方式计算一个数字的阶乘值。清单2.17的输出如下所示:
![053-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-05.jpg?sign=1739897106-fVc6cUIgI4P60Tfu7hE6HEzyFFt5F9TP-0-88d35443bd5c472a302698c53421ba84)
除了递归方式之外,还可以用迭代的方式计算数字的阶乘值。清单2.18的Factorial2.py
说明了如何使用range()
函数来计算一个正整数的阶乘值。
清单2.18 Factorial2.py
![053-06](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/053-06.jpg?sign=1739897106-CXFrDovo595iL1aHTufmYLMA2MTAwAxg-0-dc4e5893e13506d1beba56b12c5016ec)
清单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=1739897106-oRTi3VdurIyrof0cxSREI6RHpmvsA9v8-0-aa7307d6a369d7a174cca55f60fbb889)
2.5.2 计算斐波那契数
斐波那契数代表了自然界中一些有趣的模式(比如向日葵模式),它的递归定义如下:
![054-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-02.jpg?sign=1739897106-R3ZacFg7HibvWIC3PMhymu28du4SMVVI-0-a009bdee6b596def2fa4747121d49999)
清单2.19的fib.py
说明了如何计算斐波那契数。
清单2.19 fib.py
![054-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-03.jpg?sign=1739897106-TJMs1aQbDvYNkt66g5uHTenLAl7igpNb-0-ea8d668d308c6f88ed18f33bd199d5a4)
清单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=1739897106-hG8nhryZYwkLY8SnCyr80X5uGyQKmO2A-0-58ba2859099a21c4e4fc38aa87aca30b)
2.5.3 计算两个数的最大公约数
两个正整数的最大公约数(GCD)是指可以整除两个数的最大整数。比如:
![054-05](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-05.jpg?sign=1739897106-TU9KHGMWpQkAvgrU7tt7IhrpTXRcobPT-0-84cedb84f692a0aa5f89340d88cb144e)
清单2.20通过递归和欧几里得算法来查找两个数的最大公约数。
清单2.20 gcd.py
![054-06](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/054-06.jpg?sign=1739897106-SGj52WDBrTYwdCVkyLWT1Gm555aw807e-0-3b8b80b1a6b802c272acb642ac8fe151)
清单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=1739897106-PK8RwY2UDwIAlPyA6T11TMEiiaOBwHET-0-9c2762a5b69dc97ed0e16a8229c4581d)
2.5.4 计算两个数的最小公倍数
两个正整数的最小公倍数(LCM)是两个数的倍数的最小整数。比如:
![055-02](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-02.jpg?sign=1739897106-1lcHKneOzbmegERVo5JIbERIsEaFuyf5-0-a424d8f5419752993e399416b482ec46)
通常,两个正整数x
和y
,你可以按如下所示计算它们的最小公倍数:
![055-03](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-03.jpg?sign=1739897106-6iFbfOk5PbN6V9xzd57YbFznI1UQqs2f-0-ef4bd3d688c7bf73247b8df471011838)
清单2.21的代码使用前面定义的gcd()
函数来计算两个正整数的最小公倍数。
清单2.21 lcm.py
![055-04](https://epubservercos.yuewen.com/8036B4/21821545908478506/epubprivate/OEBPS/Images/055-04.jpg?sign=1739897106-o1YiIF3vswaGGras1Re7sUnxrcapgtw9-0-0b21d704c90c876758f8933d35340d33)
清单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=1739897106-Ay26C2TT79VqbTbzM7JaJJHn4lM8zBvC-0-0820912b917d7aaca74f42b150dc0459)