動態規劃

1.兩個相似問題解的不同:

  • 問題一:給定一個數字n和一個數組nums(上述全爲正整數),能否在nums的子集中找到一組數使得這組數的和爲n。
  • 問題二:給定一個數字n和一個數組nums(上述全爲正整數),能否使用nums中的數字拼出(求和)數字n(或者找到最少的個數拼出n)。

問題一是一個揹包問題,轉化爲揹包問題就是包的大小爲n,有一些大小爲nums的物品,能否正好裝下某些物品。需要使用二維數組來解決。

問題二具有可重複性,使用一維數組即可解決。

 

2.模版化解決子序列子數組問題:

一般來說,這類問題都是讓你求一個最長子序列,因爲最短子序列就是一個字符嘛,沒啥可問的。一旦涉及到子序列和最值,那幾乎可以肯定,考察的是動態規劃技巧,時間複雜度一般都是 O(n^2)。

  • 模版一:
int n = array.length;
int[] dp = new int[n];

for (int i = 1; i < n; i++) {
    for (int j = 0; j < i; j++) {
        dp[i] = 最值(dp[i], dp[j] + ...)
    }
}
  • 模版二:
int n = arr.length;
int[][] dp = new dp[n][n];

for (int i = 0; i < n; i++) {
    for (int j = 1; j < n; j++) {
        if (arr[i] == arr[j]) 
            dp[i][j] = dp[i][j] + ...
        else
            dp[i][j] = 最值(...)
    }
}

3.連續子數組與連續子序列的概念

連續子數組一般不用使用動態規劃,後者因爲不需要物理上連續,可採用動態規劃。

 

4.最長迴文子串,迴文子串個數以及最長迴文子序列,迴文子序列個數

子串與子序列不同,轉移方程和條件也不同。但他們使用相同的思路就是dp[i][j]表示第i個字符到第j個字符之間的迴文個數。For循環如下:

for i in range(s_len - 1, -1, -1):
            for j in range(i + 1, s_len):
                if s[i] == s[j]:
                    dp[i][j] = ......
                else:
                    dp[i][j] = ......

5.最長公共子串,最長公共子序列

子串是連起來的,子序列可以分開。

子串:dp[i][j]代表s1從0到i,s2從0到j最長的公共子串,如果s1[i] == s2[j],那麼dp[i][j] = dp[i - 1][j - 1] + 1,否則dp[i][j] = 0.如果0->i,0->j之前有公共子串,那也是沒用的,關鍵取決於s[i] 是否等於s[j],因爲這裏是求子串最大長度。

子序列:dp[i][j]代表s1從0到i,s2從0到j中,注意這裏是‘中’,最長的公共子序列,因爲序列可以分開,所以可以考慮之前的最長公共子序列。如果s1[i] == s2[j],那麼dp[i][j] = dp[i - 1][j - 1] + 1,否則dp[i][j] = max(dp[i -1][j], dp[i, j - 1]).

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章