Believing Process 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

public static String longestPalindrome2(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }
        int maxLen = 1;
        int begin = 0;
        char[] cs = s.toCharArray();
        // dp[i][j]:表示s[i][j]是否是回文串
        boolean[][] dp = new boolean[len][len];
        // 初始化:单独一个字符肯定是回文子串
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }
        // j为右边界,i为左边界
        for (int j = 1; j < len; j++) {
            for (int i = 0; i < j; i++) {
                // 首尾不相等时,必不是回文串
                if (cs[i] != cs[j]) {
                    dp[i][j] = false;
                } else {
                    // 首尾相等时,有2种情况
                    // 情况1:s[i...j]长度不超过3,不用检查必为回文串
                    // 情况2:s[i...j]长度大于3,由s[i+1...j-1]来判断
                    dp[i][j] = j - i + 1 <= 3 || dp[i + 1][j - 1];
                }
                // 更新max和begin
                if (dp[i][j] && j - i + 1 > maxLen) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substring(begin, begin + maxLen);
    }

         这题用暴力破解法遍历所有的子串,会超过时间限制,所以采用动态规划的方法。

        dp[i][j]表示索引从i到j的子串是否为回文串,值为boolean类型。

         边界条件:

  1. 当子串长度为1时,是回文串。 即dp[i][i] = true;        
  2. 当子串长度为2时,只要它的两个字母相同,它就是一个回文串。

        状态转移方程:

        dp[i][j] = dp[i+1][j-1]&&(下标为i的字符==下标为j的字符),当两者都满足的时候,此时dp[i][j] = true,是回文串。

        在双层for循环里面,j是右边界,i是左边界。当首尾不相同时,此时的子串肯定不是回文串,直接标记为false,若首尾相同,则有两种情况:

  1. 若此时的子串长度若不超过3,则子串是一个回文串。
  2. 若此时的子串长度超过3,则由 dp[i+1][j-1]来判断。

        然后更新最大子串长度以及子串开始的下标,最后返回子串。

上一篇:c#获取当前进程使用内存


下一篇:704. 二分查找