Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
Input: "babad" Output: "bab" Note: "aba" is also a valid answer.
Example:
Input: "cbbd" Output: "bb"
方法
1.
(Dynamic Programming) [Accepted]
To improve over the brute force solution, we first observe how we can avoid unnecessary re-computation while validating palindromes. Consider the case ”ababa”. If we already knew that ”bab” is a palindrome, it is obvious that ”ababa” must be a palindrome since the two left and right end letters are the same.
We define P(i,j) as following:
Therefore,
P(i,j)=(P(i+1,j−1) and Si==Sj)
The base cases are:
P(i,i)=true
P(i,i+1)=(Si==Si+1)
This yields a straight forward DP solution, which we first initialize the one and two letters palindromes, and work our way up finding all three letters palindromes, and so on...
Complexity Analysis
-
Time complexity : O(n2). This gives us a runtime complexity of O(n2).
-
Space complexity : O(n2). It uses O(n2) space to store the table.
Additional Exercise
Could you improve the above space complexity further and how?
代码1(递归编写 结果: Submission Result: Time Limit Exceeded):
class Solution {
public:
int ispalindromic(string s,int start,int end,int n,int left,int right,string &substring){
if(left<start){
substring = s.substr(left+1,n);
return n;
}
if(end<right){
substring = s.substr(left+1,n);
return n;
}
if(s[left]==s[right]){
return ispalindromic(s,start,end,n+2,left-1,right+1,substring);
}
else{
substring = s.substr(left+1,n);
return n;
}
}
public:
string longestPalindrome(string s) {
int len = s.length();
string maxsubstring;
int Maxlen = -1;
string tmpstring;
for(int i = 0;i<len;i++){
int sublen = ispalindromic(s,0,len-1,1,i-1,i+1,tmpstring);
if(Maxlen<sublen){
Maxlen = sublen;
maxsubstring = tmpstring;
}
if(s[i]==s[i+1]){
int sublen = ispalindromic(s,0,len-1,2,i-1,i+2,tmpstring);
if(Maxlen<sublen){
Maxlen = sublen;
maxsubstring = tmpstring;
}
}
}
return maxsubstring;
}
};
代码2 (非递归编写,但也运用了把大问题转化为小问题的想法,将多种个情况归为一种处理):
class Solution {
public:
int ispalindromic(string s,int start,int end,int n,int left,int right,string &substring){
while(true){
if(left<start){
substring = s.substr(left+1,n);
return n;
}
if(end<right){
substring = s.substr(left+1,n);
return n;
}
if(s[left]==s[right]){
n+=2;
left-= 1;
right+= 1;
}
else{
substring = s.substr(left+1,n);
return n;
}
}
}
public:
string longestPalindrome(string s) {
int len = s.length();
string maxsubstring;
int Maxlen = -1;
string tmpstring;
for(int i = 0;i<len;i++){
int sublen = ispalindromic(s,0,len-1,1,i-1,i+1,tmpstring);
if(Maxlen<sublen){
Maxlen = sublen;
maxsubstring = tmpstring;
}
if(s[i]==s[i+1]){
int sublen = ispalindromic(s,0,len-1,2,i-1,i+2,tmpstring);
if(Maxlen<sublen){
Maxlen = sublen;
maxsubstring = tmpstring;
}
}
}
return maxsubstring;
}
};
方法
2.
Approach #4 (Expand Around Center) [Accepted]
In fact, we could solve it in O(n2) time using only constant space.
We observe that a palindrome mirrors around its center. Therefore, a palindrome can be expanded from its center, and there are only 2n−1 such centers.
You might be asking why there are 2n−1 but not n centers? The reason is the center of a palindrome can be in between two letters. Such palindromes have even number of letters (such as ”abba”) and its center are between the two ’b’s.
Complexity Analysis
-
Time complexity : O(n2). Since expanding a palindrome around its center could take O(n) time, the overall complexity is O(n2).
-
Space complexity : O(1).
代码 :
class Solution {
public:
int expandAroundcenter(string s,int left,int right){
while(left>=0 && right<s.length() && s[left]==s[right]){
left--;
right++;
}
return right - left -1;
}
public:
string longestPalindrome(string s) {
int start = 0,end = 0;
for(int i=0;i<s.length();i++){
int len1 = expandAroundcenter(s,i,i);
int len2 = expandAroundcenter(s,i,i+1);
int len = max(len1,len2);
if(len>end - start){
start = i-(len -1)/2;
end = i +len/2;
end +=1;
}
}
cout<<start<<end - start<<endl;
return s.substr(start,end - start);
}
};