LeetCode-5-最长回文子串


题意描述:

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。


示例:

示例一:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例二:

输入: "cbbd"
输出: "bb"

解题思路:

Alice: 我用 Python 实现的暴力算法居然超时了。 hhh(’∇’)シ┳━┳
Bob: 再用 C++ 或者 Java 试一试,说不定能过。
Alice; 还有别的方法吗 ? 这题有点像动态规划呀,我都能找到递推公式对应的关系了。如果子串 s[i][j] 是回文的而且 s[i-1] == s[j + 1] 那么 s[i-1][j+1] 也是回文的。
Bob: 不错不错,还有一个问题,如果最长的回文字符串长度是偶数怎么办 ?
Alice: 偶数也可以处理啊,只要保证 在计算 dp[i-1][j+1] 的时候已经计算出 dp[i][j] 的值就好了。
Bob: 那这样的话,我们在初始化的时候要做两次,一次是长度是 1 的子串,一次是长度是 2 的子串。这样算长度为 3 的回文子串的时候用到 第一次初始化的值,计算长度为 4 的回文子串的时候用到 第二次初始化的值。然后一直这样算下去…
Alice: 对,就是这样,很典型的一个 二维动态规划的问题嘛。
Bob: hhh😎


代码:

Python 方法一:双重循环暴力求解。

class Solution:
    def longestPalindrome(self, s: str) -> str:

        if len(s) <= 1:
            return s
            # 处理边界值条件

        ans = 1
        ret = s[0]
        # 双重循环,遍历所有可能的子串
        for x in range(0, len(s)):
            for y in range(x+1, len(s)):
                if self.isPalindrome(s[x:y+1]):
                    if y - x + 1 > ans:
                        ans = y - x + 1
                        ret = s[x:y+1]
        return ret

    def isPalindrome(self, s: str) -> bool:
        # 判断一个字符串是不是回文字符串
        return s[::-1] == s

Java 方法一: 双重循环暴力求解。

class Solution {
    public String longestPalindrome(String s) {

        if(s.length() <= 1){
            return s;
        }else{

            int maxLength = 1;
            String answer = "" + s.charAt(0);
            for(int i=0; i<s.length(); ++i){
                for(int j=i+1; j<s.length(); ++j){
                    if(j-i+1 > maxLength){
                        if(isPalindrome(s.substring(i, j+1))){
                            maxLength = j-i+1;
                            answer    = s.substring(i, j+1);
                        }
                    }
                }
            }
            return answer;
        }
    }
    public 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;
    }
}

Python方法二: 二维 动态规划,通过。😎

class Solution:
    def longestPalindrome(self, s: str) -> str:

        if len(s) < 2:
            return s

        # initiation
        maxValue = 0
        left     = 0
        right    = 0 
        dp = [[0 for x in range(len(s))] for z in range(len(s))]
        #dp[i][j] == 1 即数组中下标为 i,j 的子串是回文子串
        for x in range(len(s)-1):
            dp[x][x] = 1
            if s[x] == s[x+1]:
                dp[x][x+1] = 1
                maxValue   = 2
                left       = x
                right      = x + 1
        dp[len(s)-1][len(s)-1] = 1
        

        for strlen in range(3, len(s) + 1):
            for l in range(0, len(s)-strlen+1):
                if s[l] == s[l + strlen - 1] and dp[l+1][l + strlen - 2] == 1:
                    dp[l][l + strlen - 1] = 1
                    if dp[l][l + strlen - 1] == 1 and strlen > maxValue:
                        maxValue = strlen
                        left = l
                        right = l + strlen - 1
                        #print(left, right, maxValue)
        #print(left, right)
        return s[left:right+1]

Java 方法二: 动态规划。

class Solution {
    public String longestPalindrome(String s) {
        if(s.length() < 2){
            return s;
        }else{
            int[][] dp   = new int[s.length()][s.length()];
            int maxValue = 0;
            int left     = 0;
            int right    = 0;
            for(int i=0; i<s.length()-1; ++i){
                dp[i][i] = 1;
                if(s.charAt(i) == s.charAt(i + 1)){
                    dp[i][i+1] = 1;
                    maxValue   = 2; 
                    left       = i;
                    right      = i + 1;
                }
            }
            for(int len=3; len<=s.length(); ++len){
                for(int l=0; l<=s.length()-len; ++l){
                    if(s.charAt(l) == s.charAt(l+len-1) && dp[l+1][l+len-2] == 1){
                        dp[l][l+len-1] = 1;
                        if(len > maxValue){
                            maxValue = len;
                            left     = l;
                            right    = l+len-1;
                        }
                    }
                }
            }
            return s.substring(left, right+1);
        }
    }
}

易错点:

  • 一些测试样例:
"ababa"
"abcda"
"aaaaaaaaaaaaaaaaaaaaaaaaaa"
"dsdsdfsdf"
"ab"
"aa"
"a"
""
  • 答案:
"ababa"
"a"
"aaaaaaaaaaaaaaaaaaaaaaaaaa"
"dsdsd"
"a"
"aa"
"a"
""

总结:

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值