1. 程式人生 > >分治:分治和動態規劃的區別,二分檢索遞迴和迭代方式實現

分治:分治和動態規劃的區別,二分檢索遞迴和迭代方式實現

分治法

分治一般可以直接使用遞迴實現,在不考慮空間消費的情況下和迭代方式時間消耗相差不多

==================================================================

分治一般形式: 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