LeetCode - 5 最长回文子串

题目来源

5. 最长回文子串 - 力扣(LeetCode)

题目描述

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2

输入:s = "cbbd"
输出:"bb"

提示

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

题目解析

本题数量级不大,可以考虑暴力破解。

最简回文串有两种:

  • 单个字符的子串:比如 "b"
  • 两个相同字符的子串:比如 "bb"

基于最简回文子串,我们向其两端扩展,比如最简回文子串的范围是 s[i],那么可以定义 L = i , R = i,只要 s[L] == s[R],则回文子串扩展成功,新的回文子串范围是  s[L, R],然后按此逻辑继续扩展 L--,R++,直到发现 s[L] != s[R] 时,停止扩展,最后 s[L+1, R - 1] 就是一个拓展处理的回文子串。

同理,比如最简回文子串时 s[i, i+1],那么可以定义 L = i ,R = i + 1,只要 s[L] == s[R],则回文子串扩展成功,新的回文子串范围是  s[L, R],然后按此逻辑继续扩展 L--,R++,直到发现 s[L] != s[R] 时,停止扩展,最后 s[L+1, R - 1] 就是一个拓展处理的回文子串。

我们可以发现,最简回文子串 s[i] 和 s[i, i+1] 的拓展逻辑是相同的,区别仅在于初始状态不同,即

  • 初始状态 s[i],可以看成 s[i+0, i+0]
  • 初始状态 s[i, i+1],可以看成 s[i+0, i+1]

因此,提取增量部分,记录到 offsets 中,即 offsets = [[0, 0], [0, 1]]

C源码实现

char* longestPalindrome(char* s) {
    int maxLen = 0; // 记录最长回文子串的长度
    int resL = 0; // 记录最长回文子串的起始位置

    int offsets[2][2] = {{0, 0}, {0, 1}}; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]

    for (int i = 0; i < strlen(s); i++) {
        for (int k = 0; k < 2; k++) {
            int l = i + offsets[k][0];
            int r = i + offsets[k][1];

            while (l >= 0 && r < strlen(s) && s[l] == s[r]) { // 扩展逻辑
                l--;
                r++;
            }

            int len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1

            if (len > maxLen) { // 更新最长回文子串
                maxLen = len;
                resL = l + 1;
            }
        }
    }

    s[resL + maxLen] = '\0'; // 原地修改
    return s + resL;
}

C++源码实现

class Solution {
public:
    string longestPalindrome(string s) {
        int maxLen = 0;  // 记录最长回文子串的长度
        int resL = 0; // 记录最长回文子串的起始位置

        int offsets[2][2] = {{0, 0}, {0, 1}}; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]

        for (int i = 0; i < s.length(); i++) {
            for (int k = 0; k < 2; k++) {
                int l = i + offsets[k][0];
                int r = i + offsets[k][1];

                while (l >= 0 && r < s.length() && s[l] == s[r]) { // 扩展逻辑
                    l--;
                    r++;
                }

                int len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1

                if (len > maxLen) { // 更新最长回文子串
                    maxLen = len;
                    resL = l + 1;
                }
            }
        }

        return s.substr(resL, maxLen);
    }
};

Java源码实现

class Solution {
    public String longestPalindrome(String s) {
        int maxLen = 0; // 记录最长回文子串的长度
        int resL = 0; // 记录最长回文子串的起始位置

        int[][] offsets = { { 0, 0 }, { 0, 1 } }; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]

        for (int i = 0; i < s.length(); i++) {
            for (int[] offset : offsets) {
                int l = i + offset[0];
                int r = i + offset[1];

                while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) { // 扩展逻辑
                    l--;
                    r++;
                }

                int len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1

                if (len > maxLen) { // 更新最长回文子串
                    maxLen = len;
                    resL = l + 1;
                }
            }
        }

        return s.substring(resL, resL + maxLen);
    }
}

Python源码实现

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        maxLen = 0  # 记录最长回文子串的长度
        resL = 0  # 记录最长回文子串的起始位置

        offsets = ((0, 0), (0, 1))  # 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]

        for i in range(len(s)):
            for offset in offsets:
                l = i + offset[0]
                r = i + offset[1]

                while l >= 0 and r < len(s) and s[l] == s[r]:  # 扩展逻辑
                    l -= 1
                    r += 1
                
                length = r - l - 1  # [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1

                if length > maxLen:  # 更新最长回文子串
                    maxLen = length
                    resL = l + 1
        
        return s[resL:resL + maxLen]

JavaScript源码实现

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function (s) {
    let maxLen = 0; // 记录最长回文子串的长度
    let resL = 0; // 记录最长回文子串的起始位置

    const offsets = [[0, 0], [0, 1]]; // 记录两种最简回文串的初始增量, s[i+0, i+0] 和 s[i+0, i+1]

    for (let i = 0; i < s.length; i++) {
        for (let offset of offsets) {
            let l = i + offset[0];
            let r = i + offset[1];

            while (l >= 0 && r < s.length && s[l] == s[r]) { // 扩展逻辑
                l--;
                r++;
            }

            const len = r - l - 1; // [l + 1, r - 1]范围是回文串, 其长度为 (r - 1) - (l + 1) + 1

            if (len > maxLen) { // 更新最长回文子串
                maxLen = len;
                resL = l + 1;
            }
        }
    }

    return s.slice(resL, resL + maxLen);
};

你可能感兴趣的:(LeetCode刷题笔记,leetcode,算法,Java,JavaScript,Python,C,C++)