1. 首页

LeetCode 005. 最长回文子串

题目描述

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

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
Js 中 文 网 - 全球前端挚爱的技术成长平台 https://www.javascriptc.com/

示例 2:

输入: "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)是否可以形成回文,
状态转移方程只是将上面的描述转化为代码即可:

if (s[i] === s[j] && dp[i + 1][j - 1]) {
  dp[i][j] = true;
}
  • 暴力匹配 (Brute Force)

  • 根据回文子串的定义,枚举所有长度大于等于 22 的子串,依次判断它们是否是回文;

  • 在具体实现时,可以只针对大于“当前得到的最长回文子串长度”的子串进行“回文验证”;
  • 在记录最长回文子串的时候,可以只记录“当前子串的起始位置”和“子串长度”,不必做截取。这一步我们放在后面的方法中实现。

关键点

  • ”延伸“(extend)

复杂度分析

  • 时间复杂度:$O(N^2)$
  • 空间复杂度:$O(N^2)$

代码

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;
};
/**
*  @作者: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;
}

/**
*  @作者: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 实现

/**
*  @作者: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;
}

/**
*  @作者: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] 是否为回文串
     * 来源:Js 中 文 网 - 全球前端挚爱的技术成长平台 https://www.javascriptc.com/
     */
    private boolean validPalindromic(char[] charArray, int left, int right) {
        while (left < right) {
            if (charArray[left] != charArray[right]) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

Python 实现

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
# @作者: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)
        # 来源:Js 中 文 网 - 全球前端挚爱的技术成长平台 https://www.javascriptc.com/
        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]

# @作者: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;
    }
}

相关题目

其他

更多题解可以访问我的 码农周刊 仓库:https://github.com/meibin08/free-programming-books, 一起学习更多前端前沿知识。

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:LeetCode 005. 最长回文子串

链接:https://www.javascriptc.com/4364.html

« 你知道Vue3为什么这么快吗
LeetCode 004. 寻找两个正序数组的中位数»
Flutter 中文教程资源

相关推荐

QR code