算法理解:分治算法一般的求解过程可以分为三个步骤:分解、求解、合并
分解:原问题可以分解为多个子问题,这些子问题与原问题相比,只是问题的规模有所降低,其结构和求解方法与原问题相同或相似。
求解:对划分好的子问题进行求解:原问题在分解过程中,递归地求解子问题
由于递归都必须有一个终止条件,因此,当分解后的子问题规模足够小时,应能够直接求解。
合并:应能够采用某种方式、方法合并或构造出原问题的解。在分治策略中,由于子问题与原问题在结构和解法上的相似性,用分治方法解决的问题,大都采用了递归的形式。在各种排序方法中,如归并排序、堆排序、快速排序等,都存在有分治的思想 。
问题实例:最小值问题:求n个元素的最小值。
问题分析:求n个元素的最小值,是一个很简单的问题,只要求得n个元素的最小值即可,通常情况下我们能想到的的是暴力的求法,可以利用循环来做,即我们只要假设第一个元素最小,通过循环比较每一个数,在进行交换就可以求出来。但是时间复杂度是O(n)的,学习了分治算法,我们就要深刻理解这个状态,我们能不能找到更加简单的算法来解决这个问题。
问题建模:先分再治,所以我们就要将元素分为两部分分别求解,再合起来求解。
算法描述:先创建一个数组用于存放n个数组,定义一个getmin函数用于求最小值,getmin函数传入一个数组和两个参数,分别表示左端点和右端点,定义分治的中点,从分治中点分开,分别递归去找到左右两部分的最小值,再将左右两部分的最小值进行合并求出最小的那个便是整个数组中最小的元素。
算法源码:
def getmin(arr,l,r):
if r-l<=1: #递归出口
if arr[l]<arr[r]:
return arr[l]
else:
return arr[r]
mid=(l+r)//2 #以中点分为左右两个部分
left_min=getmin(arr,l,mid) #分别递归处理左右两个部分
right_min=getmin(arr,mid+1,r)
if left_min<right_min: #比较两部分最小值,返回更小的值便是最小值
return left_min
else:
return right_min
arr=[]
n=int(input("请输入数的个数:")) #n是数组的个数
for i in range(n): #循环读入数据放入arr数组中
x=input()
arr.append(x)
print("最小值为:",getmin(arr,0,len(arr)-1))
测试数据
第一组:
输入 4
2 1 5 7
输出:1
第二组:
输入 6
4 2 9 5 3 9
输出:2
第三组:
输入 10
4 2 8 6 1 0 6 3 8 -5
输出:-5