【3】分治法(divide-and-conquer)
阿新 • • 發佈:2018-12-13
分治法
顧名思義,分治法是將一塊完整的領土分解為若干小的領土,然後一塊塊征服。
- 分,把一個問題的例項劃分為若干個子問題(原問題規模變小)
- 治,遞迴地解決每個子問題
- 把每一個子問題的解整合為一個大問題的解
舉例
歸併排序(Merge sort)
- 將待排序的陣列一分為二
- 遞迴地對每一個子陣列排序
- 合併兩個有序的子陣列為一個有序的陣列(線上性時間n內)
歸併排序可以用a=2,b=2,k=0的主方法求解
二分查詢方法(Binary search)
演算法描述:設某個元素為x,需要在一個已經排序的陣列中找到這個x。
- 分,把x與陣列中間的元素比較
- 治,如果x小於中間元素,取前一半陣列,否則取後一半,每次只在一個數組遞迴
- 合併,無計算量
乘方問題(Powering a number)
演算法描述:給出一個數(實數或者浮點數)和正整數,計算。 傳統的Naive演算法直接按照的定義,個連乘計算,演算法複雜度為。 利用分治法:
- 分
- 當為偶數,將分為,即,兩個只要算一個就可以,所以子規模的規模變為。
- 當為奇數,將分為,即,兩個只要算一個就可以,所以子規模的規模變為。
- 治,類似二分查詢,只要在一部分遞迴即可
- 合併
斐波那契數(Fibonacci numbers)
傳統的Naive演算法
傳統的Naive演算法按照定義向前逐步遞迴。
樸素平方遞迴式
斐波那契數列特性之一:取最近的整數就是第n個斐波那契數。即,此時斐波那契數列變成了乘方問題。演算法複雜度為。
此演算法的問題在於,在計算的儲存中,用浮點數儲存和,因此會影響到結果。 真正的平方遞迴式 利用特性同樣能將斐波那契問題轉化為乘方問題。演算法複雜度為。
矩陣乘法(Matrix multiplication)
樸素演算法
樸素演算法複雜度
分治法
- 分,矩陣分塊,如圖,分為8塊
- 治,遞迴每一個子矩陣
- 合併,將子矩陣合併
矩陣分為8個子矩陣,規模變為,合併的時間為矩陣相加的演算法複雜度為,最終的複雜度為,並沒有更優。
分治法 Strassen’s idea
分析思路:我們不在乎矩陣加法的演算法複雜度(是可以接受的),演算法優化應該從分塊迭代部分考慮(減少乘法的次數)。
利用主方法的Case1情況求解,演算法複雜度為,比原來的大大優化(特別是在n較大的情況下效果顯著)。
超大規模積體電路(VLSI layout)
假設電路是個二叉樹,現在有個n個葉結點的完全二叉樹,演算法目的在於找到網格佔空間最小的方法。
改變佈局,充分利用空白區域。