这是我参与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)