給定字符串,能夠經過插入字符,使其變爲迴文。求最少插入字符的數量。例如:緩存
ab最少插入1個字符,變爲*b*abapp
aa最少插入0個字符blog
abcd最少插入3個字符,*dcb*abcd遞歸
這個題目的分析思路,和前面兩期是很是類似的:給出遞歸的解法,發現重複的子問題,改進爲動態規劃的解法,這是一個分析的過程,待同窗們比較熟悉時候,能夠直接給出動態規劃的解決方案,就很好了。字符串
這個題目,遞歸該如何解呢?給定一個字符串str,長度爲n,怎麼插入最少的字符,是的字符串變爲迴文呢?插入最少的字符,就是要儘可能利用原來的字符,在原字符串str中,儘可能利用更多可以匹配的字符。怎麼對這個問題進行分解呢?考慮str字符串總體:get
若是str[0]==str[n-1],則問題轉變爲求str[1,n-2],插入最少字符,獲得迴文it
若是str[0]!=str[n-1],則須要插入一個字符要麼和str[0]相同,要麼和str[n-1]相同,class
若是和str[0],則轉變爲str[1,n-1],插入最少字符,獲得迴文循環
若是和str[n-1],則轉變爲str[0,n-2],插入最少字符,獲得迴文方法
上面的第2種狀況中,須要取兩個值最小值。則完成了問題的分解,而且,基本狀況也分析徹底,則有遞歸式爲:
fmi(str, l, h) = (str[l] == str[h]) ? fmi(str, l+1, h-1) : (min(fmi(str, i+1, h), fmi(str,l, h-1))+1)
經過上面的式子,有經驗的、熟練的同窗,很直接的就能看出來,存在重複的子問題,這就意味着,咱們能夠講子問題的解緩存使用。若是,沒有直接可以看出來的同窗們,仍是能夠按照咱們以前的方法,把遞歸樹畫出來吧,那樣更加一目瞭然。
那麼,這個題目該如何用動態規劃的解決呢?如何重複利用子問題的解呢?彷佛有些不那麼直接。但其實也是於規律可循的。上面的遞歸式,是從字符串的兩 邊,想中間移動遞歸,根據動態規劃解決問題的思想,咱們先解決子問題,再重複利用子問題,就是要從內向外解決,你們還記得迴文子串判斷的那個題目麼,動態 規劃解法的外層循環是子串的長度,這個題目也是相似的。示例代碼以下: