算法练习Day14[LeetCode]5. 最长回文子串

5. 最长回文子串

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

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

示例 2:
输入:s = "cbbd"
输出:"bb"

示例 3:
输入:s = "a"
输出:"a"

示例 4:
输入:s = "ac"
输出:"a"
 提示:
1. 1 <= s.length <= 1000
2. s 仅由数字和英文字母(大写和/或小写)组成

法一:动态规划
对于一个子串而言,如果它是回文串,并且长度大于 2,那么将它首尾的两个字母去除之后,它仍然是个回文串。例如对于字符串 “ababa”,如果我们已经知道“bab” 是回文串,那么“ababa” 一定是回文串,这是因为它的首尾两个字母都是“a”。

class Solution {
     
    public String longestPalindrome(String s) {
     
        int n = s.length();
        boolean[][] dp = new boolean[n][n];//存放true或false
        String ans = "";//初始化ans
        for (int l = 0; l < n; ++l) {
     
            for (int i = 0; i + l < n; ++i) {
     
                int j = i + l;
                if (l == 0) {
     
                //如果字串长度为1,则是回文数
                    dp[i][j] = true;
                } else if (l == 1) {
     
                //如果字串长度为2,则判断两个元素是否相等
                    dp[i][j] = (s.charAt(i) == s.charAt(j));
                } else {
     
                //子串长度大于 2时,判断首和尾字符是否相同,且判断s[i+1,j-1]是否时回文子串
                    dp[i][j] = (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]);
                }
                //最长回文字串
                if (dp[i][j] && l + 1 > ans.length()) {
     
                    ans = s.substring(i, i + l + 1);
                }
            }
        }
        return ans;
    }
}


复杂度分析
1. 时间复杂度:O(n^2),其中 n是字符串的长度。动态规划的状态总数为 O(n^2),对于每个状态,我们需要转移的时间为 O(1)2. 空间复杂度:O(n^2),即存储动态规划状态需要的空间。


法二:中心扩展算法
我们枚举所有的「回文中心」并尝试「扩展」,直到无法扩展为止,此时的回文串长度即为此「回文中心」下的最长回文串长度。我们对所有的长度求出最大值,即可得到最终的答案。

class Solution {
     
    // 主函数
    public String longestPalindrome(String s) {
     
        // 记录最长回文串
        String res = "";

        // 穷举以所有点(奇数一个点,偶数两个点)为中心的回文串
        for (int i = 0; i < s.length(); i++) {
     
            // 当回文串是奇数时,由一个中心点向两边扩散
            String s1 = palindrome(s, i, i);
            // 当回文串是偶数时,由中间的两个中心点向两边扩散
            String s2 = palindrome(s, i, i + 1);

            // 三元运算符:判断为真时取冒号前面的值,为假时取冒号后面的值
            res = res.length() > s1.length() ? res : s1;
            res = res.length() > s2.length() ? res : s2;
        }

        return res;
    }

    // 辅助函数:寻找回文串
    private String palindrome(String s, int left, int right) {
     
        // 在区间 [0, s.length() - 1] 中寻找回文串,防止下标越界
        while (left >=0 && right < s.length()) {
     
            // 是回文串时,继续向两边扩散
            if (s.charAt(left) == s.charAt(right)) {
     
                left--;
                right++;
            } else {
     
                break;
            }
        }

        // 循环结束时的条件是 s.charAt(left) != s.charAt(right), 所以正确的区间为 [left + 1, right), 方法 substring(start, end) 区间是 [start, end), 不包含 end
        return s.substring(left + 1, right);
    }
}
复杂度分析
1. 时间复杂度:O(n^2),其中 n 是字符串的长度。长度为 12 的回文中心分别有 n 和 n-1 个,每个回文中心最多会向外扩展 O(n)次。
2. 空间复杂度:O(1)

你可能感兴趣的:(leetcode,JAVA,leetcode)