前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >005. 最长回文子串 | Leetcode题解

005. 最长回文子串 | Leetcode题解

作者头像
苏南
发布2020-12-16 14:48:11
4420
发布2020-12-16 14:48:11
举报
文章被收录于专栏:漫画前端

点击上方“蓝色字体”,选择“设为星标

每天复习一道面试题,轻松拿大厂Offer~

题目描述

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

示例 1:

代码语言:javascript
复制
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:

代码语言:javascript
复制
输入: "cbbd"
输出: "bb"

难度:

  • 难度:中等
  • 支持语言:JavaScriptJavaPython

相关标签

  • 回文
  • 动态规划
  • 字符串

相关企业

  • 阿里
  • 百度
  • 腾讯

思路

这是一道最长回文的题目,要我们求出给定字符串的最大回文子串。

5.longest-palindromic-substring

解决这类问题的核心思想就是两个字“延伸”,具体来说如果在一个不是回文字符串的字符串两端添加任何字符,或者在回文串左右分别加不同的字符,得到的一定不是回文串

5.longest-palindromic-substring-2

base case 就是一个字符(轴对称点是本身),或者两个字符(轴对称点是介于两者之间的虚拟点)。

5.longest-palindromic-substring-3

事实上,上面的分析已经建立了大问题和小问题之间的关联,基于此,我们可以建立动态规划模型。

我们可以用 dp[i][j] 表示 s 中从 i 到 j(包括 i 和 j)是否可以形成回文, 状态转移方程只是将上面的描述转化为代码即可:

代码语言:javascript
复制
if (s[i] === s[j] && dp[i + 1][j - 1]) {
  dp[i][j] = true;
}
  • 暴力匹配 (Brute Force)
  • 根据回文子串的定义,枚举所有长度大于等于 22 的子串,依次判断它们是否是回文;
  • 在具体实现时,可以只针对大于“当前得到的最长回文子串长度”的子串进行“回文验证”;
  • 在记录最长回文子串的时候,可以只记录“当前子串的起始位置”和“子串长度”,不必做截取。这一步我们放在后面的方法中实现。

关键点

  • ”延伸“(extend)

复杂度分析

  • 时间复杂度:
  • 空间复杂度:

代码

JavaScript 实现
代码语言:javascript
复制
/**
 * @来源:Javascript中文网 - 前端进阶资源教程 https://www.javascriptc.com/
 * @介绍:前端中文网是以前端进阶资源教程分享为主的专业网站,包括:前端、大厂面试题、typescript教程、程序人生、React.js
 * @lc app=leetcode id=5 lang=javascript
 *
 * [5] Longest Palindromic Substring
 */
/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function (s) {
  // babad
  // tag : dp
  if (!s || s.length === 0) return "";
  let res = s[0];

  const dp = [];

  // 倒着遍历简化操作, 这么做的原因是dp[i][..]依赖于dp[i + 1][..]
  for (let i = s.length - 1; i >= 0; i--) {
    dp[i] = [];
    for (let j = i; j < s.length; j++) {
      if (j - i === 0) dp[i][j] = true;
      // specail case 1
      else if (j - i === 1 && s[i] === s[j]) dp[i][j] = true;
      // specail case 2
      else if (s[i] === s[j] && dp[i + 1][j - 1]) {
        // state transition
        dp[i][j] = true;
      }

      if (dp[i][j] && j - i + 1 > res.length) {
        // update res
        res = s.slice(i, j + 1);
      }
    }
  }

  return res;
};
代码语言:javascript
复制
/**
*  @作者:salter
*  @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-chuan-by-fanzhanxiang/
*/
var longestPalindrome = function(s) {
   let ans = '';
    let n = s.length;
    let dp = Array.from(new Array(n), () => new Array().fill(0));
    for(let i = n-1; i >=0; i--) {
        for(let j = i; j < n; j++) {
            dp[i][j] = s[i] === s[j] && ( j - i < 2 || dp[i+1][j-1])
            if(dp[i][j] && j - i + 1 > ans.length) {
                ans = s.substr(i,j - i + 1);
            }
        }
    }
    return ans;
}

代码语言:javascript
复制
/**
*  @作者:liuxukang
*  @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-pu-tong-de-dong-tai-gui-hua-by-liuxukang/
*/
var longestPalindrome = function (s) {
    if(!s && s < 2) return s
    let len = s.length;
    let start = 0
    let end = 0;
    const calcPalindrome = (left,right) => {
        while(left >=0 && right < len && s[left] === s[right]){
            left--;
            right++;
        }

        return right -left -1
    }

    for(let i = 0; i < len; i++) {
        let s1 = calcPalindrome(i,i)
        let s2 = calcPalindrome(i,i+1)
        let maxLen = Math.max(s1,s2)
        if(maxLen > end -start ) {
            start = i - Math.floor((maxLen - 1) / 2)
            end = i + Math.floor(maxLen /2)
        }
    }
    return s.slice(start,end+1)
}


Java 实现
代码语言:javascript
复制
/**
*  @作者:windliang
*  @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-bao-gu/
*/
public boolean isPalindromic(String s) {
  int len = s.length();
  for (int i = 0; i < len / 2; i++) {
   if (s.charAt(i) != s.charAt(len - i - 1)) {
    return false;
   }
  }
  return true;
 }

// 暴力解法
public String longestPalindrome(String s) {
    String ans = "";
    int max = 0;
    int len = s.length();
    for (int i = 0; i < len; i++)
        for (int j = i + 1; j <= len; j++) {
            String test = s.substring(i, j);
            if (isPalindromic(test) && test.length() > max) {
                ans = s.substring(i, j);
                max = Math.max(max, ans.length());
            }
        }
    return ans;
}

代码语言:javascript
复制
/**
*  @作者:liweiwei1419
*  @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/
*/
public class Solution {

    public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }

        int maxLen = 1;
        int begin = 0;
        // s.charAt(i) 每次都会检查数组下标越界,因此先转换成字符数组
        char[] charArray = s.toCharArray();

        // 枚举所有长度大于 1 的子串 charArray[i..j]
        for (int i = 0; i < len - 1; i++) {
            for (int j = i + 1; j < len; j++) {
                if (j - i + 1 > maxLen && validPalindromic(charArray, i, j)) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substring(begin, begin + maxLen);
    }

    /**
     * 验证子串 s[left..right] 是否为回文串
     */
    private boolean validPalindromic(char[] charArray, int left, int right) {
        while (left < right) {
            if (charArray[left] != charArray[right]) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

Python 实现
代码语言:javascript
复制
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        if n == 0:
            return ""
        res = s[0]
        def extend(i, j, s):
            while(i >= 0 and j < len(s) and s[i] == s[j]):
                i -= 1
                j += 1
            return s[i + 1:j]

        for i in range(n - 1):
            e1 = extend(i, i, s)
            e2 = extend(i, i + 1, s)
            if max(len(e1), len(e2)) > len(res):
                res = e1 if len(e1) > len(e2) else e2
        return res
代码语言:javascript
复制
# @作者:skay2002
# @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/pythonshuang-bai-50msyi-lun-bian-li-fa-5-zui-chang/

class Solution:
    def longestPalindrome(self, s: str) -> str:
        if not s: return ""
        length = len(s)
        if length == 1 or s == s[::-1]: return s
        max_len,start = 1,0
        for i in range(1, length):
            even = s[i-max_len:i+1]
            odd = s[i-max_len-1:i+1]
            if i - max_len - 1 >= 0 and odd == odd[::-1]:
                start = i - max_len - 1
                max_len += 2
                continue
            if i - max_len >= 0 and even == even[::-1]:
                start = i - max_len
                max_len += 1
                continue
        return s[start:start + max_len]

代码语言:javascript
复制
# @作者:LeetCode-Solution
# @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/

class Solution {
    public String longestPalindrome(String s) {
        int n = s.length();
        boolean[][] dp = new boolean[n][n];
        String ans = "";
        for (int l = 0; l < n; ++l) {
            for (int i = 0; i + l < n; ++i) {
                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 > ans.length()) {
                    ans = s.substring(i, i + l + 1);
                }
            }
        }
        return ans;
    }
}

相关题目

  • 516.longest-palindromic-subsequence
  • https://www.javascriptc.com/special/leetcode

其他

  • 原题leetcode链接:https://leetcode-cn.com/problems/longest-palindromic-substring/
  • 合作方:JavaScript中文网 – 全球极客挚爱的技术成长平台
  • 说明:leetcode 题解 | 每日一题? 所有题目并非全部为本人解答,部分为在复习学习中整理提取其他解题作者的优秀笔记,便于大家学习共同进步,如有侵权,请联系删除。

- -

关注公众号「IT平头哥联盟」,一起进步,一起成长!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 画漫画的程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 难度:
  • 相关标签
  • 相关企业
  • 思路
  • 关键点
  • 复杂度分析
  • 代码
    • JavaScript 实现
      • Java 实现
        • Python 实现
        • 相关题目
          • 其他
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档