Approach 1
本题我是先用动态规划解出的,其实我觉得动态规划也足矣了,不过还有更好的方法.
复杂度分析:
- 时间复杂度:
- 空间复杂度: 不过我做了一定的优化,变成了
代码如下:
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.isEmpty()) {
return s;
}
int len = s.length();
boolean[][] isPalin = new boolean[2][len]; // i: currentLen % 2, j: startIdx
for (int i = 0; i < len; ++i) {
isPalin[0][i] = true;
isPalin[1][i] = true;
}
int maxLen = 1;
int targetIdx = 0;
for (int l = 2; l <= len; ++l) {
for (int idx = 0; idx <= len - l; ++idx) {
if (isPalin[l%2][idx+1] && s.charAt(idx) == s.charAt(idx+l-1)) {
isPalin[l%2][idx] = true;
if (l > maxLen) {
maxLen = l;
targetIdx = idx;
}
}
else {
isPalin[l%2][idx] = false;
}
}
}
return s.substring(targetIdx, targetIdx + maxLen);
}
}
不过在此基础上,可以将空间复杂度降为,我们使用动态规划的原因是因为动态规划可以记忆一些东西,避免重复计算,但是在本道题中,仔细看看就会发现,其实相对于自底向上的方法,自顶向下的方法并没有做大量重复计算,所以动态规划是不必要的。
Approach 2
利用镜像,设定一个pivot,然后不断扫描左右两边的值
复杂度分析:
- 时间复杂度:
N
个pivot,扫描每个需要,整体复杂度是 - 空间复杂度:不需要记忆任何东西,所以是
代码如下:
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.isEmpty()) {
return s;
}
int maxLen = 1;
int startIdx = 0;
for (int i = 0; i < s.length(); ++i) {
int len1 = expand(s, i, i);
int idx1 = i - len1 / 2;
int len2 = expand(s, i, i + 1);
int idx2 = i - len2 / 2 + 1;
if (len1 > maxLen) {
maxLen = len1;
startIdx = idx1;
}
if (len2 > maxLen) {
maxLen = len2;
startIdx = idx2;
}
}
return s.substring(startIdx, startIdx + maxLen);
}
private int expand(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
--left;
++right;
}
return (right - 1) - (left + 1) + 1;
}
}