Go&Java算法之最长回文子串

183 阅读1分钟

这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

最长回文子串

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

 

示例 1:

输入:s = "babad"

输出:"bab"

解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"

输出:"bb"  

提示:

1 <= s.length <= 1000

s 仅由数字和英文字母组成

题解

算法一:动态规划(Java)

动态规划就是为了减少重复计算的问题。动态规划听起来很高大上。其实说白了就是空间换时间,将计算结果暂存起来,避免重复计算。作用和工程中用 redis 做缓存有异曲同工之妙。

我们用一个 boolean dp[l][r] 表示字符串从 i 到 j 这段是否为回文。试想如果 dp[l][r]=true,我们要判断 dp[l-1][r+1] 是否为回文。只需要判断字符串在(l-1)和(r+1)两个位置是否为相同的字符,是不是减少了很多重复计算。

进入正题,动态规划关键是找到初始状态和状态转移方程。

初始状态,l=r 时,此时 dp[l][r]=true。

状态转移方程,dp[l][r]=true 并且(l-1)和(r+1)两个位置为相同的字符,此时 dp[l-1][r+1]=true。

class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() == 0 || s.length() < 2) {
            return s;
        }
        int len = s.length();
        boolean[][] dp = new boolean[len][len];
        int begin = 0;
        int maxLength = 1;

        // 初始化
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        for (int j = 1; j < len; j++) {
            for (int i = 0; i < j; i++) {
                if (s.charAt(i) != s.charAt(j)) {
                    dp[i][j] = false;
                } else {
                    if (j - i < 3) {
                        dp[i][j] = true;
                    } else {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                    if (dp[i][j] && j - i + 1 > maxLength) {
                        begin = i;
                        maxLength = j - i + 1;
                    }
                }
            }
        }
        
        return s.substring(begin, begin + maxLength);
    }
}

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

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

算法一:动态规划(Go)

思路同上

func longestPalindrome(s string) string {
    n := len(s)
    dp := make([][]bool, n)
    for i,_ := range dp {
        dp[i] = make([]bool, n)
    }
    ans := ""
    for l:=0; l<n; l++ { // l为本次循环遍历的子串长度
        for i:=0; i+l<n; i++ {
            j := i+l
            if l == 0 {
                dp[i][j] = true
            } else if l == 1 {
                dp[i][j] = (s[i] == s[j])
            } else {
                dp[i][j] = (s[i] == s[j] && dp[i+1][j-1])
            }
            if dp[i][j] && l+1 > len(ans) {
                ans = s[i:j+1]
            }
        }
    }
    return ans
}

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

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