leetcode5 最长回文子串

文章目录

  • 1.解法
    • 1.1 暴力法
    • 1.2 中心扩散
    • 3.3 动态规划
  • 2.原题

1.解法

1.1 暴力法

按顺序,找出所有子串并判断比较

class Solution {
    public String longestPalindrome(String s) {
        int max = 0;//记录 最长回文子列的 长度
        String str = null;//记录 最长回文子列
        for (int i = 0; i < s.length(); i++) {
            for (int j = i + 1; j <= s.length(); j++) {
                int len = j - i;//记录 当前子列的 长度
                String curr = s.substring(i, j);//记录 当前子列; substring左闭右开
                if (isPalindrome(curr)){
                    if (len > max){
                        max = len;
                        str = curr;
                    }
                }
            }
        }
        return str;
    }

    private boolean isPalindrome(String s){
        for (int i = 0; i < s.length() / 2; i++) {
            if(s.charAt(i) != s.charAt(s.length() - 1 - i)){
                return false;
            }
        }
        return true;
    }
}

可以通过测试用例,但是会超出时间限制

时间复杂度 O ( n 3 ) O(n^3) O(n3)

空间复杂度 O ( 1 ) O(1) O(1)


1.2 中心扩散

大致思路就是选一个字符,然后向两边找,判断是否组成一个回文字符串

例如 bcba,以c为单个中心点,即search(“bcba”, 1, 1),发现s.charAt(0)==s.charAt(2),记录下来,最后得到最长子串就是bcb

需要注意的是,单个索引为中心点(找到的子串长度为奇数)和两个索引为中心点(找到的子串长度为偶数)的情况都要查找

class Solution {
    public String longestPalindrome(String s) {
        if (s.isEmpty()){
            return null;
        }
        if (s.length() == 1){
            return s;
        }

        String str = s.substring(0,1);//记录 最长回文子列
        for (int i = 0; i < s.length(); i++) {
            
            String tmp = search(s, i, i);
            if (tmp.length() > str.length()){
                str = tmp;
            }

            tmp = search(s, i, i + 1);
            if (tmp.length() > str.length()){
                str = tmp;
            }
        }
        return str;
    }

    private String search(String s, int begin, int end){
        while(begin >= 0 && end < s.length() && s.charAt(begin) == s.charAt(end)){
            begin--;
            end++;
        }
        return s.substring(begin + 1, end);
    }
}

时间复杂度 O ( n 2 ) O(n^2) O(n2)

空间复杂度 O ( 1 ) O(1) O(1)


3.3 动态规划

s [ i , j ] s[i,j] s[i,j]:代表字符串 s s s 从索引 i i i 到索引 j j j 处的子串

d p [ i ] [ j ] = { 1 , s [ i , j ] 为回文子串 0 , i > j 即 s [ i , j ] 不存在或者 s [ i , j ] 不是回文子串 dp[i][j]=\begin{cases}1,s[i,j]为回文子串\\0,i>j即s[i,j]不存在或者s[i,j]不是回文子串\end{cases} dp[i][j]={1,s[i,j]为回文子串0,i>js[i,j]不存在或者s[i,j]不是回文子串

使用动态规划就是为了利用过去已经计算得到的信息,即 d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] ∧ ( s i = = s j ) dp[i][j]=dp[i+1][j-1]\land(s_i==s_j) dp[i][j]=dp[i+1][j1](si==sj)

例如basbbs d p [ 3 ] [ 4 ] = 1 dp[3][4]=1 dp[3][4]=1 并且 字符串s 在索引2 和 索引5 处的字符相同( s 2 = = s 5 s_2==s_5 s2==s5),那么 d p [ 2 ] [ 5 ] = 1 dp[2][5]=1 dp[2][5]=1,即 s [ 2 , 5 ] s[2,5] s[2,5]是回文子串。

需要注意边界条件,当子串为1个字符时,就是回文的;2个字符时,只要相同,就是回文

class Solution {
    public static String longestPalindrome(String s) {
        int len = s.length();//字符串长度
        if(len <= 1)
            return s;

        int max = 0;//记录 最长子串的 长度
        String str = s.substring(0, 1);//记录 最长子串
        int[][] dp = new int[len][len];

        //初始化,单个字符就是回文子串
        for (int i = 0; i < len; i++) {
            dp[i][i] = 1;
        }

        //初始化,两个字符如果相同就是回文
        for (int i = 0; i < len - 1; i++) {
            if (s.charAt(i) == s.charAt(i + 1)){
                dp[i][i+1] = 1;
                str = s.substring(i, i + 2);
            }
        }

        //外层循环控制子串的长度,因为长度为1和2的已经在上面初始完成,所以从长度3开始
        for (int l = 3; l <= len; l++) {
            //控制子串的左边界,为了防止右边界j越界,用 i < len - l 控制
            for (int i = 0; i <= len - l; i++) {
                //右边界j根据 j-i+1=l 可以计算得到 j=l+i-1
                int j = l + i - 1;//右边界

                //当S_i==S_j时,dp[i][j]是否为1就由dp[i + 1][j - 1]决定
                if(s.charAt(i) == s.charAt(j)){
                        dp[i][j] = dp[i + 1][j - 1];
                }else{
                    //不等时,s[i,j]不是回文子串,则dp[i][j]=0
                    dp[i][j] = 0;
                }
                if(dp[i][j] == 1 && j - i + 1 > max){
                    max = j - i + 1;
                    str = s.substring(i, j + 1);
                }
            }
            
        }
        return str;
    }
}

2.原题

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

    如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

    示例 1:

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

    示例 2:

    输入:s = "cbbd"
    输出:"bb"
    

    提示:

    • 1 <= s.length <= 1000
    • s 仅由数字和英文字母组成

你可能感兴趣的:(算法,leetcode,数据结构)