分而治之(divide and conquer)是一种著名的递归式问题解决方法。
使用分而治之的思想解决问题的过程包括两个步骤:
- 找出基线条件,这种条件必须尽可能简单。
- 不断将问题分解(缩小规模),直到符合基线条件。
书中提出了几个具体的例子来解释分而治之的思想。如果有一个农场主,有一块地,我们如何让将这块地分成大小相同的方块,并且分出的方块要尽可能大。
首先,我们可以利用循环来解决这个问题。 把要分的小方块的边长当作循环变量,每次循环检查土地的边长是否为小方块边长的整数倍。分析到这里,博主突然发现,这个问题原来就是找出土地的两条边的最大公因数。
其次,书中提出了按照分而治之的思想想出的一种递归方式。
该算法的基础是欧几里得算法,“适用于这个小块地的最大方块,也是适用于整块地的最大方块”
- 找出基线条件。当一条边的长度是另一条边的整数倍时,就可以停止算法。
- 缩小问题的规模。首先找出这块地可以容纳的最大方块,然后对余下的土地调用算法。
D&C并非可用于解决问题的算法,而是一种解决问题的思路。
下面再看一个例子:给定一个数组对数组进行求和。
利用循环解决很简单,见代码实现,不再累述。
```python
#利用循环对数组进行求和
#python 3.7
#小灿 2018-12-3
def mysum(arr):
total = 0
for i in arr:
total += i
return total
print(mysum([1,2,3,4,5]))
如何使用递归函数来完成这个任务呢?
第一步 找出基线条件。我们知道最简单的数组是空数组或者是只有一个元素的数组,对这两种数序进行求和是非常简单的。
- 空数组,不包含任何元素,总和为0
- 单元素数组,只包含一个元素,总和为元素值
经过分析,基线条件就是上面的条件。
第二步 如何缩小问题规模呢?每次递归调用都减少数组元素的数目。
函数的工作原理如下所示。
一个特例函数的执行过程能够更好地帮助我们理解递归。
tips:涉及数组的递归函数时,基线条件是数组为空或只包含一个元素。
求和的递归实现过程如下。
```python
#利用递归对数组进行求和
#python 3.7
#小灿 2018-12-3
def mysum(arr):
total = 0
if len(arr) == 1:
return arr[0]
else:
total = arr[0]+mysum(arr[1:len(arr)])
return total
total = mysum(arr=[1,2,3,4,5])
print(str(total))
为了巩固对递归算法的理解,我们将进一步利用递归算法实现两个例子。一个是利用递归函数来计算列表中包含的元素数,第二个是找出列表中的最大的元素,由于都很简单,直接给出代码。
```python
#python 3.7
#小灿 2018-12-3
def mycount(arr):
#利用递归计数
if arr == []:
return 0
else:
return 1 + count(list[1:])
def max(arr):
#利用递归求最大值
if len(arr) == 2:
if arr[0] > arr[1]:
return arr[0]
else:
return arr[1]
else :
sub_max = max(list[1:])
if arr[0] > sub_max :
return arr[0]
else:
return sub_max