【Leetcode-005】最长回文子串(Java && C++实现)


1 双指针(Java实现)

解法1:双指针-左右指针(Java实现)

/*
    方法2:双指针-左右指针
    思路:使用双指针(左右指针)的方法判断回文字符串,可同时解决回文串长度为奇数和偶数的情况
          通过遍历原字符串的各个索引(作为回文串的中心节点-向两边扩散),调用回文字符串函数,求解最大值
    时间复杂度:O(n * n)
    空间复杂度:O(1)常数空间
*/
class Solution {
    
    
    public String longestPalindrome(String s) {
    
    
        //边界条件
        if(s == null || s.length() == 0) return "";

        String res = "";
        //遍历字符串的各个索引,作为回文串的中心节点(奇数长度和偶数长度)
        for(int i = 0; i < s.length(); i++){
    
    
            //长度为奇数的回文串(中心为同一个,左右指针重合)
            String str1 = Palindrome(s, i, i);
            //长度为偶数的回文串(中心有两个,左右指针相邻)
            String str2 = Palindrome(s, i, i + 1);

            res = res.length() > str1.length() ? res : str1;
            res = res.length() > str2.length() ? res : str2;
        }
        return res;
    }

    //判断是否为回文字符串串
    public String Palindrome(String s, int left, int right){
    
    
        //防止索引越界,且两端字符相同 → 指针分别向两侧移动
        while(left >= 0 && right < s.length() && (s.charAt(left) == s.charAt(right))){
    
    
            left--;
            right++;
        }

        //返回回文字符串
        //注意:while循环终止条件为 left = -1 或 right = s.length()
        return s.substring(left + 1, right);
    }
}

2 动态规划(Java实现)

解法2:动态规划(Java实现)

/*
    方法1:动态规划
    思路:定义dp数组:dp[i][j]:字符串s[i...j]是否为回文字符串
          状态转移:dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1]
    时间复杂度:O(n * n)
    空间复杂度:O(n * n)    开辟二维dp数组
    类似题目:t516 最长回文子序列

    动态规划(空间换时间) 时间复杂度O(n*n)     空间复杂度O(n*n)
    状态:dp[i][j] 表示子串s[i..j]是否为回文子串
    状态转移方程:dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1]  //子串的回文性质决定整体串的回文性质
    边界条件:子问题 (j-1) - (i+1) + 1 < 2时,即子串长度小于2时,无需检查子串是否回文(必回文)
    初始化:dp[i][i] = true
*/

/*
class Solution {
    public String longestPalindrome(String s) {
        //边界条件:字符串长度为0或1
        if(s == null || s.length() == 0) return "";
        if(s.length() == 1) return s;

        //字符串长度大于1
        int maxLen = 1;     //最长回文子串的长度:用于截取回文串
        int n = s.length();  //字符串长度
        int start = 0;      //起始索引
        int end = 0;        //结束索引

        boolean [][] dp = new boolean[n][n];    //dp状态数组
        //长度为1的子串
        for(int i = 0; i < n; i++){
            dp[i][i] = true;
        }

        //长度为2的子串
        for(int i = 0; i < n-1; i ++){
            if(s.charAt(i) == s.charAt(i+1)){
                dp[i][i+1] = true;
                start = i;
                maxLen = 2;
            }
        }

        //长度大于等于3的子串
        for(int k = 3; k <= n; k++){    //子串长度
            for(int i = 0; i < n - k + 1; i++){    //start索引的可取范围:0 ~ n-k
                int j = i + (k - 1);    //end索引值: end = start + (k-1);
                if(s.charAt(i) == s.charAt(j) && dp[i+1][j-1]){  //子串首尾字符相同 && 子串子问题的dp状态为true
                    dp[i][j] = true;
                    if(k > maxLen){    //满足条件的回文子串的长度k
                        start = i;  //记录start索引
                        maxLen = k;
                    }
                }
            }
        }
        return s.substring(start, start + maxLen);     //截取子串(包左不包右)
    }
}
*/

3 双指针(C++实现)-待更新

4 动态规划(C++实现)-待更新

猜你喜欢

转载自blog.csdn.net/newson92/article/details/113810958
今日推荐