程序员社区

LeetCode-5-最长回文子串

5. 最长回文子串

难度中等3546收藏分享切换为英文接收动态反馈

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

示例 1:

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

示例 2:

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

示例 3:

输入:s = "a"
输出:"a"

示例 4:

输入:s = "ac"
输出:"a"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母(大写和/或小写)组成

通过次数557,383

提交次数1,640,287


暴力法

LeetCode-5-最长回文子串插图
image-20210420223046462

动态规划

LeetCode-5-最长回文子串插图1
image-20210420223200857
LeetCode-5-最长回文子串插图2
image-20210421083944019

s[i,j]的长度为j-i+1

左闭右闭([])的数组长度为j-i+1左闭右开([)])的数组长度为j-i+1

当j-i+1小于等于2时候 如果 如果s[i]==s[j] 则dp[i][j] = true 否则,为false

LeetCode-5-最长回文子串插图3
image-20210421084941143

如果s[i,j]的长度(j-i+1)>2 时候

LeetCode-5-最长回文子串插图4
image-20210421085825101
LeetCode-5-最长回文子串插图5
image-20210421090027488
LeetCode-5-最长回文子串插图6
image-20210421090609401
LeetCode-5-最长回文子串插图7
image-20210421090828199

动态规划code:

 public String longestPalindrome(String s) {
        if (s == null) return null;
        char[] cs = s.toCharArray();
        if (cs.length <= 1) return s;
        // 最长回文子串的长度(至少是1)
        int maxLen = 1;
        // 最长回文子串的开始索引
        int begin = 0;
        boolean[][] dp = new boolean[cs.length][cs.length];
        // 从下到上(i由大到小)
        for (int i = cs.length - 1; i >= 0; i--) {
            // 从左到右(j由小到大)
            for (int j = i; j < cs.length; j++) {
                // cs[i, j]的长度
                int len = j - i + 1;
                dp[i][j] = (cs[i] == cs[j]) && (len <= 2 || dp[i + 1][j - 1]);
                if (dp[i][j] && len > maxLen) { // 说明cs[i, j]是回文子串
                    maxLen = len;
                    begin = i;
                }
            }
        }
        return new String(cs, begin, maxLen);
    }
LeetCode-5-最长回文子串插图8
image-20210421091106973

LeetCode-5-最长回文子串插图9
image-20210421094751310

以字符为中心向左右扩展

public String longestPalindromeEx(String s) {
        if (s == null) return null;
        char[] cs = s.toCharArray();
        if (cs.length <= 1) return s;
        // 最长回文子串的长度(至少是1)
        int maxLen = 1;
        // 最长回文子串的开始索引
        int begin = 0;

        for (int i = cs.length - 2; i >= 1; i--) {
            // 以字符为中心向左右扩展
            int len1 = palindromeLength(cs, i - 1, i + 1);
            // 以字符右边的间隙为中心向左右扩展
            int len2 = palindromeLength(cs, i, i + 1);
            len1 = Math.max(len1, len2);
            if (len1 > maxLen) {
                maxLen = len1;
                begin = i - ((maxLen - 1) >> 1);
            }
        }
        // 以0号字符右边的间隙为中心的最长回文子串长度是2
        if (cs[0] == cs[1] && maxLen < 2) {
            // cs[0, 1]就是最长的回文子串
            begin = 0;
            maxLen = 2;
        }
        return new String(cs, begin, maxLen);
    }
    
    /**
     * @return 从l开始向左、从r开始向右扫描,获得的最长回文子串的长度
     */
    private int palindromeLength(char[] cs, int l, int r) {
        while (l >= 0 && r < cs.length && cs[l] == cs[r]) {
            l--;
            r++;
        }
        return r - l - 1;
    }
LeetCode-5-最长回文子串插图10
image-20210421095025787

扩展2

LeetCode-5-最长回文子串插图11
image-20210421100230592
public static String longestPalindromeEx2(String s) {
        if (s == null) return null;
        char[] cs = s.toCharArray();
        if (cs.length <= 1) return s;
        // 最长回文子串的长度(至少是1)
        int maxLen = 1;
        // 最长回文子串的开始索引
        int begin = 0;
        int i = 0;
        while (i < cs.length) {
            int l = i - 1;
            // 找到右边第一个不等于cs[i]的位置
            int r = i;
            while (++r < cs.length && cs[r] == cs[i]);
            // r会成为新的i
            i = r;
            
            // 从l向左,从r向右扩展
            while (l >= 0 && r < cs.length && cs[l] == cs[r]) {
                l--;
                r++;
            }
            
            // 扩展结束后,cs[l + 1, r)就是刚才找到的最大回文子串
            // ++l后,l就是刚才找到的最大回文子串的开始索引
            int len = r - ++l;
            if (len > maxLen) {
                maxLen = len;
                begin = l;
            }
        }
        return new String(cs, begin, maxLen);
    }
LeetCode-5-最长回文子串插图12
image-20210421100545373

马拉车(Manacher)算法

留空位,彻底学习一下Manacher算法!

赞(0) 打赏
未经允许不得转载:IDEA激活码 » LeetCode-5-最长回文子串

一个分享Java & Python知识的社区