给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:输入: "cbbd"
输出: "bb"
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
动态规划,但是时间复杂度O(n^2),勉强跑过
class Solution {
private static final String EMPTY = "";
/**
* 动态规划
*
* 1. 状态定义
* f(x) = 以x元素坐标为中心的回文
* 2. 状态转移方程
* f(x) = f(2 * x - i) + f(x) + f(i), x = 0 ~ i
*
* 时间复杂度O(n^2),此解超时
*
* @param s
* @return
*/
public String longestPalindrome(String s) {
int len = s.length();
// 加上这个判断勉强跑过了
if (len == 0 || s.replace(String.valueOf(s.charAt(0)), "").length() == 0) {
return s;
}
String[] palindrome = new String[2 * len + 1];
String max = "";
for (int i = 0; i < 2 * len + 1; i++) {
char iCh = getChar(s, i);
setChar(palindrome, s, i);
for (int j = 0; j <= i; j++) {
int before = 2 * j - i;
if (before < 0 || getChar(s, before) != iCh || !needPalindrome(j, i, palindrome[j])) {
continue;
}
palindrome[j] = iCh + (palindrome[j] == null ? "" : palindrome[j]) + iCh;
if (palindrome[j].length() > max.length()) {
max = palindrome[j];
}
}
}
return max.replace(String.valueOf(Character.MIN_VALUE), "");
}
/**
* 只有连续的元素是回文才能算是回文
*
* @param position 回文中心
* @param index 最外的字符
* @param palindrome 当前的回文
* @return
*/
private boolean needPalindrome(int position, int index, String palindrome) {
int curLen = palindrome == null ? 0 : palindrome.length();
return index - position == curLen / 2 + 1;
}
/**
* index是填充后的坐标,s是为填充的字符串,获取对应的字符需要进行转换
*
* @param s
* @param index
* @return
*/
private char getChar(String s, int index) {
if (index % 2 == 0) {
return Character.MIN_VALUE;
}
return s.charAt(index / 2);
}
private void setChar(String[] palindrome, String s, int index) {
if (index % 2 == 0) {
palindrome[index] = EMPTY;
} else {
palindrome[index] = String.valueOf(s.charAt(index / 2));
}
}
}
运行效率
动态规划v2
class Solution {
/**
* 动态规划
*
* 1. 状态定义
* f[begin][end]: 坐标i到j字符串是否是回文
*
* 2. 状态转移方程
* f[begin][end] = f[begin+1][end-1] && (s[begin] == s[end]), (begin <= end)
*
* @param s
* @return
*/
public String longestPalindrome(String s) {
if (s.length() == 0) {
return s;
}
int maxLen = 1, maxLeft = 0, maxRight = 0;
boolean[][] f = new boolean[s.length()][s.length()];
// 初始状态
for (int i = 0; i < s.length(); i++) {
// 单个元素都是回文
f[i][i] = true;
}
for (int end = 1; end < s.length(); end++) {
for (int begin = 0; begin < end; begin++) {
if (s.charAt(begin) != s.charAt(end)) {
continue;
}
if (end - begin < 3 || f[begin + 1][end - 1]) {
f[begin][end] = true;
if (end - begin + 1 > maxLen) {
maxLen = end - begin + 1;
maxLeft = begin;
maxRight = end;
}
}
}
}
return s.substring(maxLeft, maxRight + 1);
}
}
运行效率
类似动态规划,比较优的O(n^2)算法
class Solution {
private int maxLen = 1; // 最大长度
private int resLeft = 0;
private int resRight = 0;
/**
* 分别以每个节点为中心进行扩散,记录最大的回文
*
* @param s
* @return
*/
public String longestPalindrome(String s) {
if (s.length() == 0) {
return s;
}
for (int i = 0; i < s.length(); i++) {
// 以i为中心,奇数元素的回文
searchPalindrome(s, i - 1, i + 1);
// 以i和i+1为中心,偶数元素的回文
searchPalindrome(s, i, i + 1);
}
return s.substring(resLeft, resRight + 1);
}
private void searchPalindrome(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
if (right - left - 1 > maxLen) {
maxLen = right - left - 1;
resLeft = left + 1;
resRight = right - 1;
}
}
}
运行效率
网友评论