<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      LeetCode dp專題

      1. 動態規劃的適用場景

      動態規劃常常適用于有重疊子問題和最優子結構性質的問題,動態規劃方法所耗時間往往遠少于樸素解法。

      2. 動態規劃的基本思想

      動態規劃背后的基本思想非常簡單。大致上,若要解一個給定問題,我們需要解其不同部分(即子問題),再合并子問題的解以得出原問題的解。
      通常許多子問題非常相似,為此動態規劃法試圖僅僅解決每個子問題一次,從而減少計算量:一旦某個給定子問題的解已經算出,則將其記憶化存儲,以便下次需要同一個子問題解之時直接查表。這種做法在重復子問題的數目關于輸入的規模呈指數增長時特別有用。

      2.1 重疊子問題

      動態規劃在查找有很多重疊子問題的情況的最優解時有效。它將問題重新組合成子問題。為了避免多次解決這些子問題,它們的結果都逐漸被計算并被保存,從簡單的問題直到整個問題都被解決。因此,動態規劃保存遞歸時的結果,因而不會在解決同樣的問題時花費時間。

      2.2 最優子結構

      動態規劃只能應用于有最優子結構的問題。最優子結構的意思是局部最優解能決定全局最優解(對有些問題這個要求并不能完全滿足,故有時需要引入一定的近似)。簡單地說,問題能夠分解成子問題來解決。

      3. 動態規劃的三要素

      • 最優子結構性質。如果問題的最優解所包含的子問題的解也是最優的,我們就稱該問題具有最優子結構性質(即滿足最優化原理)。最優子結構性質為動態規劃算法解決問題提供了重要線索。
      • 無后效性。即子問題的解一旦確定,就不再改變,不受在這之后、包含它的更大的問題的求解決策影響。
      • 子問題重疊性質。子問題重疊性質是指在用遞歸算法自頂向下對問題進行求解時,每次產生的子問題并不總是新問題,有些子問題會被重復計算多次。動態規劃算法正是利用了這種子問題的重疊性質,對每一個子問題只計算一次,然后將其計算結果保存在一個表格中,當再次需要計算已經計算過的子問題時,只是在表格中簡單地查看一下結果,從而獲得較高的效率。

      4. 動態規劃算法的設計步驟:

      1. 刻畫最優解的結構特征(尋找最優子結構)
      2. 遞歸地定義最優解的值(確定狀態轉移方程)
      3. 計算最優解的值(有兩種方法:帶備忘錄自頂向下法、自底向上法)
      4. 利用計算出的信息構造一個最優解(通常是將具體的最優解輸出)

      5. 一般的解法

      把動態規劃的解法分為自頂向下和自底向上兩種方式。
      自頂向下的方式其實就是使用遞歸來求解子問題,最終解只需要調用遞歸式,子問題逐步往下層遞歸的求解。我們可以使用緩存把每次求解出來的子問題緩存起來,下次調用的時候就不必再遞歸計算了。
      自底向上是另一種求解動態規劃問題的方法,它不使用遞歸式,而是直接使用循環來計算所有可能的結果,往上層逐漸累加子問題的解。

      注:一般看到string,往dp (dfs+memo) 上靠就對了

       

      32. Longest Valid Parentheses:

      dp[i]表示到i為止合法的()長度

      s[i] == ')' :

      dp[i] = dp[i-2] + 2                          ( s[i]=='(' )

      dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2]  ( s[i-1] == ')' && s[i-1-dp[i-1]] == '(' )

      注意判斷數組下標值是否存在

       

      72. Edit Distance

      將word1轉換成word2:

      三種操作:插入/刪除/替換 一個字符

      dp[i][j]表示word1 [0, i),word2 [0, j) 子串轉換成功時的最少轉換次數

      初始化: dp[0][j]=j 插入操作,dp[i][0]=i 刪除操作

      word1[i-1]==word2[j-1]: dp[i][j] = dp[i-1][j-1]

      word1[i-1]!=word2[j-1]:  dp[i][j] = min(dp[i-1][j-1], min(dp[i][j-1], dp[i-1][j])) + 1;

      對應三種操作:替換 dp[i-1][j-1] + 1, 刪除(word1[i-1])  dp[i-1][j] + 1,

             插入(word1[i-1]后插入word2[j-1]才兩個子串相同 <=> 刪除word2[j-1]使得兩個子串相同) dp[i][j-1] + 1 

       

      87. Scramble String

      判斷一個字符串是否由原字符串經過scramble變換得到,變換如下:

          rgeat
         /    \
        rg    eat
       / \    /  \
      r   g  e   at
                 / \
                a   t

      判斷一個字符串是scramble有兩種情況:

      把兩個字符串從中間某位置切開 

      1. s1[i...i+len-1] 左邊和 s2[j...j+len-1] 左邊部分是不是 scramble,以及s1[i...i+len-1] 右邊和 s2[j...j+len-1] 右邊部分是不是 scramble;

      2. s1[i...i+len-1] 左邊和 s2[j...j+len-1] 右邊部分是不是 scramble,以及s1[i...i+len-1] 右邊和 s2[j...j+len-1] 左邊部分是不是 scramble。

      如果以上兩種情況有一種成立,說明 s1[i...i+len-1] 和 s2[j...j+len-1] 是 scramble。

      res[i][j][len] 表示起點為s1[i]和s2[j],長度均為len的兩個子串是否為scramble。

      狀態轉移方程:res[i][j][len] = || ((res[i][j][k] && res[i+k][j+k][len-k]) || (res[i][j+len-k][k]&&res[i+k][j][len-k])) 對于所有 1<=k<len

       

      96. Unique Binary Search Trees

      dp[i]表示i個數時構成不同BST的個數

      枚舉每個數為頂點,依次劃分為左右兩部分。

      狀態轉移方程:dp[i] += (dp[j-1]*dp[i-j])  j=[1, i]

       

      115. Distinct Subsequences

      Given a string S and a string T, count the number of distinct subsequences of S which equals T.

      dp[i][j] 表示S[0, i)包含T[0, j)子串的個數

      1. General case 1: dp[i][j] = dp[i - 1][j] if t[j - 1] != s[i - 1];  s[i - 1]肯定不能在子串中
      2. General case 2: dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] if t[j - 1] == s[i - 1]; 去掉當前匹配字符的s子串
      3. Boundary case 1: dp[0][j] = 0 for all positive j;
      4. Boundary case 2: dp[i][0] = 1 for all i. 空是任何字符串的子集

      狀態轉移方程:dp[i][j] = dp[i-1][j] + ( S[i - 1] == T[j - 1] ? dp[i - 1][j - 1] : 0)

       

      97. Interleaving String

      Given s1s2s3, find whether s3 is formed by the interleaving of s1 and s2.

      dp[i][j]表示s1 [0, i), s2 [0, j)兩個字符串可以構成s3 [0, i+j)

      s1當前字符與s3當前字符相同:s1[i-1] == s3[i+j-1] 則 dp[i][j] = dp[i - 1][j]

      s2當前字符與s3當前字符相同:  s2[j-1] == s3[i+j-1] 則 dp[i][j] = dp[i][j - 1]

      狀態轉移方程:dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i - 1 + j]) || (dp[i][j - 1] && s2[j - 1] == s3[j - 1 + i]);

       

      123. Best Time to Buy and Sell Stock III

      兩次股票交易,最大利潤

      f[i, j] 表示到prices[0, j)為止i次交易的最大利潤

      狀態轉移方程:對第j天的股票是否做賣出操作

      f[i, j] = max(f[i, j-1], prices[j] - prices[k] + f[i-1, k]) { k 屬于 [0, j-1] }

              = max(f[i, j-1], prices[j] + max(f[i-1, k] - prices[k])) {利用j循環進行k循環的優化}

       

      兩個雞蛋測雞蛋摔碎的臨界樓層

      最重要的是要找到子問題。做如下的分析,假設f{n}表示從第n層樓扔下雞蛋,沒有摔碎的最少嘗試次數。第一個雞蛋,可能的落下位置[1, n], 第一個雞蛋從第i層扔下,有兩個情況:

      • 碎了,第二個雞蛋,需要從第一層開始試驗,有i-1次機會
      • 沒碎,兩個雞蛋,還有n-i層。這個就是子問題了f{n-i}

      所以,當第一個雞蛋,由第i個位置落下的時候,要嘗試的次數為1 + max(i - 1, f{n - i}),那么對于每一個i,嘗試次數最少的,就是f{n}的值。狀態轉移方程如下: f{n} = min(1 + max(i - 1, f{n - 1}) ) 其中: i的范圍為(1, n), f{1} = 1 

      推廣動態規劃,可以推廣為n層樓,m個雞蛋。如下分析: 假設f{n,m}表示n層樓、m個雞蛋時找到最高樓層的最少嘗試次數。當第一個雞蛋從第i層扔下,如果碎了,還剩m-1個雞蛋,為確定下面樓層中的安全樓層,還需要f{i-1,m-1}次,找到子問題;不碎的話,上面還有n-i層,還需要f[n-i,m]次,又一個子問題。 狀態轉移方程如下: f{n, m} = min(1 + max(f{n - 1, m - 1}, f{n - i, m}) ) 其中: i為(1, n), f{i, 1} = i

       

      posted @ 2019-07-28 22:51  demianzhang  閱讀(532)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲码和欧洲码一二三四| 粗大的内捧猛烈进出小视频| 亚洲av影院一区二区三区| 日韩精品国产精品十八禁| 无码人妻精品一区二区三区夜夜嗨| JIZZJIZZ国产| 狠狠综合久久av一区二| 国产一区二区三区禁18| 欧美亚洲h在线一区二区| 日本福利一区二区精品| 国产亚洲精品在av| 人妻精品久久无码专区涩涩| 蜜桃无码一区二区三区| 久久99精品久久久久久不卡| 日韩av不卡一区二区在线| 四虎在线播放亚洲成人| 18女下面流水不遮图| 成人网站av亚洲国产| 日本一道一区二区视频| 亚洲中文字幕aⅴ天堂| 人妻少妇精品视频三区二区| 国产精品午夜福利合集| 大田县| 久久99精品国产麻豆宅宅| 午夜通通国产精品福利| 亚洲欧美一区二区成人片| 亚洲成人av在线资源网| 亚洲天堂在线观看完整版| 国产丰满乱子伦无码专区| 一区二区三区精品偷拍| 久久精品国产色蜜蜜麻豆| 亚洲精品麻豆一二三区| 亚洲日本va午夜在线电影| 国产超碰人人做人人爰| 日日碰狠狠添天天爽五月婷| 国产av人人夜夜澡人人爽麻豆| 日韩老熟女av搜索结果| 国产一区二区三区禁18| 久久天天躁狠狠躁夜夜躁| 国产在线精品中文字幕| 精品亚洲女同一区二区|