最長回文子串(Java 動態規劃)Longest Palindromic Substring

Longest Palindromic Substring

LeetCode 原題,這里主要說一下自己的動態規劃解法和思路,希望對大家理解這個有所幫助。

暴力解法為遍歷所有子串,逐個判斷是否是回文字串。
接下來我們來優化暴力解法,暴力解法的問題在于沒有用到回文字串的特性,只是用了定義去檢驗一個字串是不是回文,所以這個題的題眼在于利用回文字串的特性。
如果一個字串是回文字串,那么去掉左右兩邊的字符之后依然是回文。
也可以說是一個回文字串,左右兩邊加上相同的字符,也是回文字串。
使用索引 ij 來表示一個字符串從索引 ij 的子串,則:

dp[i][j]表示索引i到j的子串是否是回文
dp[i][j] = true表示是回文,反之則為false

dp[i][i]只有一個字符,必是回文
關鍵點在于找到關系:dp[i][j] = dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j);
長的子串dp[i][j]依賴于短的子串dp[i + 1][j - 1],所以由短到長依次計算
1、先計算一個字符,全為true
2、再計算兩個字符,如果兩個字符一樣則為true
3、然后計算大于三個字符,直到整個字符串

1、定義二維數組存儲dp的結果值
2、單個字符(起點終點索引相同)全部為true
3、兩個字符如果字符相同為true(注意數組不要越界)
4、依次循環三個字符、四個字符......
5、有起點索引 i,有子串長度 k 則可以得到終點索引 j (同樣注意數組越界問題)
6、比較回文子串長度與保存的result長度

class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        boolean[][] dp = new boolean[len][len];//<1>
        String result = s.substring(0, 1);
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;//<2>
        }
        for (int i = 0; i < len - 1; i++) {
            dp[i][i + 1] = s.charAt(i) == s.charAt(i + 1);//<3>
            if (dp[i][i + 1]) {
                result = s.substring(i, i + 1 + 1);
            }
        }        
        //<4>
        for (int k = 3; k <= len; k++) {
            for (int i = 0; (i + k) <= len; i++) {
                int j = i + k - 1;//<5>
                dp[i][j] = dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j);
                if (dp[i][j] && (j - i + 1) > result.length()) {//<6>
                    result = s.substring(i, j + 1);
                }
            }
        }
        return result;
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。