思惟私塾——動態規劃

在刷劍指offer和LeetCode中發現,動態規劃是常常出現的一類題目,那麼接下來咱們就來仔細分析和總結下其中的套路。java

介紹

動態規劃(DP)說白了其實就是一種求解最優解的方法,是一種比較特殊的分治思想,利用它能夠對時間複雜度進行優化,其主要是根據狀態轉移方程來進行求解。面試

其內部包含了主要的兩種思想就是分治和貪心。算法

解題思路

整體來講動態規劃題目的解題思路就四步:編程

  • 狀態表示
  • 轉移方程
  • 初始狀態
  • 最終狀態

下面咱們詳細的說明一下這四步,在剛開始的時候咱們須要構建一個存儲數據的表格,通常使用數組居多,而後經過分析題目找出存在的狀態轉移方程,即從上一個狀態到下一個狀態是如何變化的,而後根據題目設置咱們的初始值,而後根據狀態轉移方程重複計算,在此過程當中利用到了前面積累下來的記錄,因此可以加快速度。最後一直倒找最終咱們所須要的狀態。數組

真題演練

咱們這邊拿劍指offer中的第47題禮物的最大價值這個典型的題目來舉例讓你們明白這個算法的思路優化

連續子數組的最大和

題目:

在一個 m*n 的棋盤的每一格都放有一個禮物,每一個禮物都有必定的價值(價值大於 0)。你能夠從棋盤的左上角開始拿格子裏的禮物,並每次向右或者向下移動一格、直到到達棋盤的右下角。給定一個棋盤及其上面的禮物的價值,請計算你最多能拿到多少價值的禮物?code

解法

本文說了是講解動態規劃的確定是要用動態規劃來解決這個問題。那咱們就按照咱們的步驟來進行blog

  • 狀態表示

設動態規劃矩陣dp[][],其中dp[i][j]表示從棋盤的左上角開始到達單元格(i,j)時能拿到禮物的最大累計價值io

  • 轉移方程

因爲只能向右或者向下移動,因此:class

    • 當i=0且j=0,爲起始元素
    • 當i=0且j≠0,爲第一行元素,只能左邊到達
    • 當i≠0且j=0,爲第一列元素,只能上邊達到
    • 當i≠0且j不等於0,可從上邊或者左邊到達

因此,狀態轉移方程以下所示:

image

  • 初始狀態

從上面分析咱們能夠知道dp[0][0]=grid[0][0]

  • 最終狀態

最終狀態就是咱們遍歷完即dp[m-1][n-1]。返回dp數組中右下角的元素

java實現

有了思路後面就是java的實現,以下所示:

class Solution {
    public int maxValue(int[][] grid) {
        int row = grid.length;
        int column = grid[0].length;
        //dp[i][j]表示從grid[0][0]到grid[i - 1][j - 1]時的最大價值
        int[][] dp = new int[row + 1][column + 1];
        for (int i = 1; i <= row; i++) {
            for (int j = 1; j <= column; j++) {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
            }
        }
        return dp[row][column];
    }
}

總結

這些就是動態規劃的全部內容了,做爲一個在LeetCode中和麪試中都常常出現的題目,能夠說是必需要掌握起來了。總之就是關注四件事情:

  • 狀態表示
  • 轉移方程
  • 初始狀態
  • 最終狀態

其中最難的就是轉移方程,這個要根據各個題目靈活處理,或者多作一些題目總結也能夠得到不錯的收穫和進步。只要有了狀態轉移方程,後面的初始狀態和邊界值再多加註意就沒有什麼大問題了。

最後

  • 若是以爲看完有收穫,但願能關注一下,順便給我點個贊,這將會是我更新的最大動力,感謝各位的支持
  • 歡迎各位關注個人公衆號【java冢狐】,專一於java和計算機基礎知識,保證讓你看完有所收穫,不信你打我
  • 求一鍵三連:點贊、轉發、在看。
  • 若是看完有不一樣的意見或者建議,歡迎多多評論一塊兒交流。感謝各位的支持以及厚愛。

——我是冢狐,和你同樣熱愛編程。

歡迎關注公衆號「Java冢狐」獲取最新消息

相關文章
相關標籤/搜索