分治:分治和動態規劃的區別,二分檢索遞迴和迭代方式實現
阿新 • • 發佈:2018-12-17
分治法
分治一般可以直接使用遞迴實現,在不考慮空間消費的情況下和迭代方式時間消耗相差不多
==================================================================
分治一般形式: T(n) = k*T(n/m) + f(n)
k為子問題個數,一般均分或者等比分
n/m問題規模,一般情況下m已經確認了子問題的個數,可以通過變換減少為a個
f(n) 為資料的處理,劃分和綜合工作量,可以增加預處理,從而減少在遞迴裡面的操作
也就是把遞迴裡面的操作儘量放在迴圈體外面處理
==================================================================
問題規模和個數k*T(n/m),k<=m,當然理論上也有T(n-m)的情況,在這種情況下子問題變得很多,且子問題可能相互依賴,不獨立,無法逐個解決,需要按照順序解決子問題,通常那種情況下使用動態規劃解決。
所以可以看出來分治和動態規劃的區別:一個子問題多,多的還有存在依賴,一個子問題少,且子問題獨立,從一般的狀態轉移方程也可以看出區別,一個是減法衰減,一個是除法衰減。
這裡還有一個思考,假如一個問題可以分解成很多個子問題,且子問題獨立,這時直接使用分治或者是直接使用動態規劃,都是和蠻力演算法沒有區別,這時就需要考慮使用分治優化策略,減少子問題k,或者通過減少步驟f(n)來優化。
二分檢索
二分檢索原問題可以看成3個情況,檢索目標就在middle,檢索目標在middle左邊,檢索目標在middle右邊,f[left,right] = f[middle] or f[left,middle-1] or f[middle+1,right],
實際上二分檢索可以看成分支限界法,arr[middle] 和 target比較剪枝,是分支限界的話,那麼就需要知道解空間,解空間就是,檢索目標的位置,通過深度增加,不斷精確檢測目標的位置,直到位置精確到1,[模糊位置,縮小範圍,縮小範圍,…,精確到1],這個過程是滿足多米諾性質的,可以用剪枝來減少搜尋空間。
#%%
# 注意遞迴的返回值,遞迴的要返回的話,要前後一致,或者直接基於某一層考慮,把遞迴看成結果
def binary_Serach_recursive(arr,left,right,target):
middle = (left + right) // 2
# 遞迴出口
if left > right :
return(-1)
if arr[middle] == target:
return(middle)
elif arr[middle] < target:
# 這裡沒有return的話,結果就沒法return出來
return binary_Serach_recursive(arr,middle+1,right,target)
else:
return binary_Serach_recursive(arr,left,middle-1,target)
def binary_Serach_iterative(arr,target):
left = 0
right = len(arr)-1
# 迴圈體條件
while left <= right:
middle = (left + right) // 2
if arr[middle] == target:
return middle
elif arr[middle] < target:
left = middle +1
else:
right = middle -1
return -1
#%%
arr = [7,3,66,33,22,66,99,0,1]
sort_arr = sorted(arr)
print(sort_arr)
print(binary_Serach_recursive(sort_arr,0,len(arr)-1,22))
print(binary_Serach_recursive(sort_arr,0,len(arr)-1,100))
print(binary_Serach_iterative(sort_arr,22))
print(binary_Serach_iterative(sort_arr,100))
[0, 1, 3, 7, 22, 33, 66, 66, 99]
4
-1
4
-1