說說你對分而治之、動態規劃的理解?區別?

林恒發表於2024-04-26

一、分而治之

分而治之是演算法設計中的一種方法,就是把一個複雜的問題分成兩個或更多的相同或相似的子問題,直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併

關於分而治之的實現,都會經歷三個步驟:

  • 分解:將原問題分解為若干個規模較小,相對獨立,與原問題形式相同的子問題
  • 解決:若子問題規模較小且易於解決時,則直接解。否則,遞迴地解決各子問題
  • 合併:將各子問題的解合併為原問題的解

實際上,關於分而治之的思想,我們在前面已經使用,例如歸併排序的實現,同樣經歷了實現分而治之的三個步驟:

  • 分解:把陣列從中間一分為二

  • 解決:遞迴地對兩個子陣列進行歸併排序

  • 合併:將兩個字陣列合並稱有序陣列

同樣關於快速排序的實現,亦如此:

  • 分:選基準,按基準把陣列分成兩個字陣列
  • 解:遞迴地對兩個字陣列進行快速排序
  • 合:對兩個字陣列進行合併

同樣二分搜尋也能使用分而治之的思想去實現,程式碼如下:

function binarySearch(arr,l,r,target){
    if(l> r){
        return -1;
    }
    let mid = l + Math.floor((r-l)/2)
    if(arr[mid] === target){
        return mid;
    }else if(arr[mid] < target ){
        return binarySearch(arr,mid + 1,r,target)
    }else{
        return binarySearch(arr,l,mid - 1,target)
    }
}

二、動態規劃

動態規劃,同樣是演算法設計中的一種方法,是一種在數學、管理科學、電腦科學、經濟學和生物資訊學中使用的,透過把原問題分解為相對簡單的子問題的方式求解複雜問題的方法

常常適用於有重疊子問題和最優子結構性質的問題

簡單來說,動態規劃其實就是,給定一個問題,我們把它拆成一個個子問題,直到子問題可以直接解決

然後呢,把子問題答案儲存起來,以減少重複計算。再根據子問題答案反推,得出原問題解的一種方法。

一般這些子問題很相似,可以透過函式關係式遞推出來,例如斐波那契數列,我們可以得到公式:當 n 大於 2的時候,F(n) = F(n-1) + F(n-2) ,

f(10)= f(9)+f(8),f(9) = f(8) + f(7)...是重疊子問題,當n = 1、2的時候,對應的值為2,這時候就透過可以使用一個陣列記錄每一步計算的結果,以此類推,減少不必要的重複計算

適用場景

如果一個問題,可以把所有可能的答案窮舉出來,並且窮舉出來後,發現存在重疊子問題,就可以考慮使用動態規劃

比如一些求最值的場景,如最長遞增子序列、最小編輯距離、揹包問題、湊零錢問題等等,都是動態規劃的經典應用場景

關於動態規劃題目解決的步驟,一般如下:

  • 描述最優解的結構
  • 遞迴定義最優解的值
  • 按自底向上的方式計算最優解的值
  • 由計算出的結果構造一個最優解

三、區別

動態規劃演算法與分治法類似,其基本思想也是將待求解問題分解成若干個子問題,先求解子問題,然後從這些子問題的解得到原問題的解

與分治法不同的是,適合於用動態規劃求解的問題,經分解得到子問題往往不是互相獨立的,而分而治之的子問題是相互獨立的

若用分治法來解這類問題,則分解得到的子問題數目太多,有些子問題被重複計算了很多次

如果我們能夠儲存已解決的子問題的答案,而在需要時再找出已求得的答案,這樣就可以避免大量的重複計算,節省時間

綜上,可得:

  • 動態規劃:有最優子結構和重疊子問題

  • 分而治之:各子問題獨立

參考文獻

  • https://baike.baidu.com/item/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/529408
  • https://juejin.cn/post/6951922898638471181

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

說說你對分而治之、動態規劃的理解?區別?

相關文章