刷
July-12-2019
前面123刷逼逼一大堆什么亂七八糟的。。
暴力O(nn)
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() <= 1) return s;
String res = "";
for (int i = 0; i < s.length(); i ++) {
String tempStr = getPalindrome(i, i, s);
if (tempStr.length() > res.length()) {
res = tempStr;
}
tempStr = getPalindrome(i, i + 1, s);
if (tempStr.length() > res.length()) {
res = tempStr;
}
}
return res;
}
public String getPalindrome(int l, int r, String s) {
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
l --;
r ++;
}
return s.substring(l + 1, r);
}
}
上來就覺得是動態規划,然后慘遭打臉,動態規划不是最優解。
其實可以理解,因為動態規划里,內層循環的String長度是從大到小,一旦發現Palindrome,那么此時內層循環的最長回文數列已經確定,按理說可以break.可是,沒進行判斷的部分以后可能被用到,所以沒法BREAK。。
public class Solution
{
public String longestPalindrome(String s)
{
if(s.length() <= 1) return s;
boolean[][] P = new boolean[s.length()][s.length()];
String res = new String();
for(int i = 0; i < s.length();i++) P[i][i] = true;
int max = 0;
for(int i = 0; i < s.length();i++)
{
for(int j = 0; j < i; j++)
{
P[j][i] = (s.charAt(j) == s.charAt(i) && (i-j <= 2 || P[j+1][i-1]));
if(P[j][i])
{
if(i-j + 1 > max)
{
max = i-j+1;
res = new String(s.substring(j,i+1));
}
}
}
}
return res;
}
}
正確的做法是backtrack. 回文判斷從中間判斷比較划算,因為一旦失敗,就沒有繼續往外判斷的意義了,可以back track。
所以就遍歷,從遍歷的位置為中心往兩邊判斷。
需要注意,ABA ABBA這倆都算回文,第一個中心是B,第二個是BB(也可以看做是BB之間的空隙)。
所以遍歷的時候,每個位置要先以當前字母為中心,再以當前字母和他右邊那個為中心。。
public class Solution
{
public String longestPalindrome(String s)
{
if(s.length() <= 1) return s;
int max = 0;
String res = new String();
for(int i = 0; i < s.length();i++)
{
int L = i, R = i;
String temp = getPlength(s,L,R);
if(temp.length() > max)
{
max = temp.length();
res = new String(temp);
}
if(i != s.length() - 1)
{
L = i; R = i + 1;
temp = getPlength(s,L,R);
if(temp.length() > max)
{
max = temp.length();
res = new String(temp);
}
}
}
return res;
}
public String getPlength(String s, int L , int R)
{
while(L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R))
{
L--;R++;
}
return s.substring(L+1,R);
}
}
時間上確實比DP要快。
然后又打臉了,發現答案里還有個O(n)的辦法。。。
上面2個都是n²:
第一個沒剪枝,用動態規划保存一些數據,不用每次判斷回文。
第二個剪枝,但是每次必須重新判斷回文,好在是從里往外,很容易break.
O(N)的還沒看。。下次刷再說吧。。
放個O(N)的傳送門
(http://articles.leetcode.com/longest-palindromic-substring-part-ii)