python分治算法_分治法及其python实现例子
在前面的排序算法學習中,歸并排序和快速排序就是用的分治法,分治法作為三大算法之一的,有非常多的應用例子。
分治法概念
將一個復雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題----“分”
將最后子問題可以簡單的直接求解----“治”
將所有子問題的解合并起來就是原問題打得解----“合”
分治法特征
該問題的規模縮小到一定的程度就可以容易地解決
該問題可以分解為若干個規模較小的相同問題,即該問題具有最優子結構性質。
利用該問題分解出的子問題的解可以合并為該問題的解;
該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子子問題。
第一條特征是絕大多數問題都可以滿足的,因為問題的計算復雜性一般是隨著問題規模的增加而增加;
第二條特征是應用分治法的前提它也是大多數問題可以滿足的,此特征反映了遞歸思想的應用;、
第三條特征是關鍵,能否利用分治法完全取決于問題是否具有第三條特征,如果具備了第一條和第二條特征,而不具備第三條特征,則可以考慮用貪心法或動態規劃法。
第四條特征涉及到分治法的效率,如果各子問題是不獨立的則分治法要做許多不必要的工作,重復地解公共的子問題,此時雖然可用分治法,但一般用動態規劃法較好。
分治法例子:
一、對數組進行快速排序
'''
時間復雜度O(nlogn)
pivot樞紐,low和high為起點終點
'''
#劃分分區(非就地劃分)
def partition(nums=list):
pivot= nums[0] #挑選樞紐
lo = [x for x in nums[1:] if x < pivot] #所有小于pivot的元素
hi = [x for x in nums[1:] if x >= pivot] #所有大于pivot的元素
returnlo,pivot,hi#快速排序
def quick_sort(nums=list):#被分解的Nums小于1則解決了
if len(nums) <= 1:returnnums#分解
lo,pivot,hi =partition(nums)#遞歸(樹),分治,合并
return quick_sort(lo) + [pivot] +quick_sort(hi)
lis= [7, 5, 0, 6, 3, 4, 1, 9, 8, 2]print(quick_sort(lis)) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
二、對數組進行歸并排序
'''名字很多:歸并排序/合并排序/二分排序
時間復雜度 O(logn)
遞歸
兩個步驟:1.拆分 2.合并'''
def merge_sort(nums=list):#取mid以及左右兩個數組
mid = len(nums)//2left_nums,right_nums=nums[:mid],nums[mid:]#遞歸分治
if len(left_nums) > 1:
left_nums=merge_sort(left_nums)if len(right_nums) > 1:
right_nums=merge_sort(right_nums)#合并
res =[]while left_nums and right_nums: #兩個都不為空的時候
if left_nums[-1] >= right_nums[-1]: #尾部較大者
res.append(left_nums.pop())else:
res.append(right_nums.pop())
res.reverse()#倒序
return (left_nums or right_nums) + res #前面加上剩下的非空nums
lis= [7, 5, 0, 6, 3, 4, 1, 9, 8, 2]print(merge_sort(lis)) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
三、給定一個順序表,編寫一個求出其最大值的分治算法
#O(nlogn)
#基本子算法(內置算法)#雖然也可以處理大數組,這里用于解決分治問題規模小于2時候
def get_max(nums=list):returnmax(nums)#分治法
defsolve(nums):
n=len(nums)if n <= 2: #分治問題規模小于2時解決
returnget_max(nums)#分解(子問題規模為 n/2)
left_list, right_list = nums[:n//2], nums[n//2:]#遞歸(樹),分治
left_max, right_max =solve(left_list), solve(right_list)#合并
returnget_max([left_max, right_max])if __name__ == "__main__":#測試數據
alist = [12,2,23,45,67,3,2,4,45,63,24,23]#求最大值
print(solve(alist)) #67
四、給定一個順序表,判斷某個元素是否在其中
#O(nlogn)#子問題算法(子問題規模為1)
defis_in_list(nums,key):if nums[0] ==key:print('Yes! %d in the nums' %key)else:print('Not found')#分治法
defsolve(nums,key):
n=len(nums)#N==1時解決問題
if n == 1:returnis_in_list(nums,key)#分解
left_list,right_list = nums[:n//2],nums[n//2:]#遞歸(樹),分治,合并
res = solve(left_list,key) orsolve(right_list,key)returnresif __name__ == '__main__':#測試
lis = [12,2,23,45,67,3,2,4,45,63,24,23]#查找
print(solve(lis,45)) #YES~
print(solve(lis,5)) #NOT~
五、找出一組序列中的第 k 小的元素,要求線性時間
'''O(nlogn)
用快排的方法,選定pivot然后通過左右兩個分組遞歸得出結果'''
#劃分
def partition(nums=list):
pi=nums[0]
lo= [x for x in nums[1:] if x
hi= [x for x in nums[1:] if x >=pi]returnlo,pi,hi#查找第 k 小的元素
defsolve(nums,key):#分解
lo,pi,hi =partition(nums)
n=len(lo)#解決
if n ==key:returnpi#遞歸分治
elif n
else:returnsolve(lo,key)if __name__ == '__main__':
lis= [3, 4, 1, 6, 3, 7, 9, 13, 93, 0, 100, 1, 2, 2, 3, 3, 2]print(solve(lis,3))#2
print(solve(lis,10))#4
總結
以上是生活随笔為你收集整理的python分治算法_分治法及其python实现例子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css 垂直居中_html中div使用C
- 下一篇: python 模块 包 库_模块(包、库