LeetCode 5. 最长回文子串

5. 最长回文子串

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

示例 1:

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

示例 2:

输入: "cbbd"
输出: "bb"
  1. 暴力法(超时)
class Solution {
    public String longestPalindrome(String s) {
       String res = new String();
       int max = 0;
       for(int i = 0;i<s.length();i++){
           //substring(i,j); [i,j) 左闭右开区间
         for(int j = i+1; j<=s.length();j++){
             //分割子字符串
             String temp = s.substring(i,j);
             //判断是否为回文子串  是赋值给res  并保存最长长度
             if(isPalidrome(temp)&&temp.length()>max){
                res = temp;
                max = Math.max(res.length(),max);
             }
         }
       }

       return res;
    }

    //判断是否为回文子串
    public static boolean isPalidrome(String arr){
        int len = arr.length();
        for(int i = 0 ;i<len/2;i++){
            //判断得到的字符串是否回文子串 不是 返回false  0与 length-1比较  1与length-1-1相比 以此类推
            if(arr.charAt(i)!=arr.charAt(len-1-i)){
                return false;
            }
        }
        return true;
    }
}
  1. 动态规划

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

    根据这样的思路,我们就可以用动态规划的方法解决本题。我们用 P(i,j)表示字符串 s 的第 i 到 j个字母组成的串(下文表示成 s[i:j])是否为回文串:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LlmsZIHY-1607434207089)(C:\Users\ADMINI~1\AppData\Local\Temp\1607429143204.png)]

    这里的「其它情况」包含两种可能性:

    • s[i, j]s[i,j] 本身不是一个回文串;

    • i > ji>j,此时 s[i, j]s[i,j] 本身不合法。

​ 那么我们就可以写出动态规划的状态转移方程:
P ( i , j ) = P ( i + 1 , j − 1 ) ∧ ( S i = = S j ) P(i, j) = P(i+1, j-1)∧(Si ==Sj) P(i,j)=P(i+1,j1)(Si==Sj)
​ 也就是说,只有 s[i+1:j-1]是回文串,并且 s 的第 i和 j个字母相同时,s[i:j]才会是回文串。

​ 对于特殊的情况

  • 当子串长度为1时,P(i,j) = true

  • 当子串长度为2时,
    P ( i , i + 1 ) = ( S i = = S i + 1 ) P(i,i+1) = (Si == Si+1) P(i,i+1)=(Si==Si+1)

图形说明

在这里插入图片描述

class Solution {
    //动态规划
    public String longestPalindrome(String s) {
    int n = s.length();
    String res="";
    boolean[][] dp = new boolean[n][n];
     for(int l=0;l<n;l++){
         //循环终止条件:i+l<n 循环只在对角线的斜上方的数据
         for(int i = 0;i+l<n;i++){
             //第一轮:dp[0][0] dp[1][1] dp[2][2] i与j相等   因为l=0
             //第二轮:dp[0][1] dp[1][2] dp[2][3] i与j差一位 因为l=1
             //第二轮:dp[0][2] dp[1][3] dp[2][4] i与j差两位 因为l=2 ......
             int j = i+l;
             if(l == 0){
                 //单个字符的情况
                dp[i][j] = true;
             }else if(l==1){
                 //临近两个字符是否相等的情况
                dp[i][j] = s.charAt(i) ==s.charAt(j);
             }else{
                 //其他情况
                dp[i][j] = (s.charAt(i) ==s.charAt(j))&&dp[i+1][j-1];
             }
             if(dp[i][j]&& l+1>res.length()){
                res= s.substring(i,i+l+1);
             }
         }
     }
    return res;
   }
}
  1. 中心扩散法

图 1 :奇数回文串与偶数回文串

class Solution {
    //动态规划
    public String longestPalindrome(String s) {
    int n = s.length();
    if(n<2) return s;
    String res="";
    int maxLength=0;
     for(int i=0;i<n-1;i++){
         String oddSearch = centerSpread(i,i,s);  //奇数个数情况
         String evenSearch = centerSpread(i,i+1,s); //偶数个数情况
         String tempRes = oddSearch.length()>evenSearch.length()?oddSearch:evenSearch;
         if(tempRes.length()>maxLength){
            maxLength = tempRes.length();
            res = tempRes;
         }
     }
    return res;
   }

   public static String centerSpread(int left,int right,String s){
         int i = left;
         int j = right;
         while(i>=0 &&j<s.length()){
             if(s.charAt(i) == s.charAt(j)){
                 //向外散开
                i--;
                j++;
             }else{
                 break;
             }
         }
         //因为最后一个i是不满足回文串的情况  所以要+1
         return s.substring(i+1,j);

   }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 最长回文子串可以通过两种方法来实现。第一种是使用中心扩展法,代码如下: ```python class Solution: def check(self, s, l, r): while l >= 0 and r < len(s) and s[l == s[r]: l -= 1 r += 1 return l + 1, r - 1 def longestPalindrome(self, s: str) -> str: start, end = 0, 0 for x in range(len(s)): l1, r1 = self.check(s, x, x) l2, r2 = self.check(s, x, x + 1) if r1 - l1 > end - start: start, end = l1, r1 if r2 - l2 > end - start: start, end = l2, r2 return s[start:end+1] ``` 第二种方法是使用动态规划,代码如下: ```python class Solution: def longestPalindrome(self, s: str) -> str: res = '' for i in range(len(s)): start = max(0, i - len(res) - 1) temp = s[start:i+1] if temp == temp[::-1]: res = temp else: temp = temp<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [5. 最长回文子串(Python 实现)](https://blog.csdn.net/d_l_w_d_l_w/article/details/118861851)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [LeetCode(Python3)5.最长回文子串](https://blog.csdn.net/weixin_52593484/article/details/124718655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [力扣 (LeetCode)刷题笔记5.最长回文子串 python](https://blog.csdn.net/qq_44672855/article/details/115339324)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值