ディレクトリ
1、タイトル
文字列を与えられた s
見つけるために、 s
最も長いサブストリングパリンドロームを。あなたは、と仮定することができる s
1000年の最大の長さ。
2、例
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
3、ソリューション
3.0ブルートフォース
最長の回文文字列を保存し、文字列が回文であるかどうかを判断するために、解決するために暴力、リストのすべてのサブ文字列:これは、他の解決策がない場合、あなたが考える必要がありますする必要があります。
public static String longestPalindrome(String s) {
String ans = "";
int max = 0;
int len = s.length();
for (int i = 0; i < len; i++) {
for (int j = i + 1; j <= len; j++) {
String tmp = s.substring(i, j);
if (isPalindromic(tmp) && tmp.length() > max) {
ans = tmp;
max = j - i;
}
}
}
return ans;
}
private static boolean isPalindromic(String s) {
int len = s.length();
for (int i = 0; i < len / 2; i++) {
if (s.charAt(i) != s.charAt(len - i - 1)) {
return false;
}
}
return true;
}
時間計算:時間複雑度はO(n³)であるように、パリンドロームO(n)の内部ループか否かを判定するためのOへのループの2つ(n²)。
宇宙複雑:O(1)、定数変数。
3.1動的なプログラミング
暴力的な解決時間の複雑さが高すぎる、我々は重複した裁判官を削除するには、いくつかの暴力的な解決策を考えることができます。
最初の定義:文字列s文字列添字jをP(i、j)の添え字iをし、インデックスi Sから文字列へのインデックスjがP(i、j)は、次いで、パリンドローム配列である場合=真、それ以外の場合はP(i、j)は=偽。下図のように:
则P(i、j)は=(P(I + 1、J - 1)&& S [I] == S [J])。
我々は(i、j)はパリンドロームの文字列を決定するための関数を呼び出す必要はありませんPの場合を知りたいのであれば、唯一の(I + 1、J-1)Pは非常に短い時間の複雑さという、ケースであることを知ってする必要がありますO(N)。したがって、我々は時間の動的プログラミング、空間の方法を使用することができ、我々はP(i、j)が格納さを得ました。
もしS [I + 1、J-1]は限りS [i]を== S [j]は、我々が決定することができ、S [I、j]がパリンドローム配列であるとして、回文配列です。
注意:
シーク長さは、Pを求めるなどのI>ここでj、[1]における式Pに経験我々[I] [J]と、1と処方しない上辺の長さときP(i、j)は2であります[2]、我々は、P [1 + 1] [2-1] = P [2] [1]を知っておく必要があり、及びP [2] [1]、S [2、1]はパリンドローム配列ではない表します私たちは一人で判断する必要があるので、これは、明らかに間違っています。
したがって、我々は最初のように式を用いて、P [I、J]のパリンドローム配列の長さを初期化する上部提案P(i、j)は=(P(I + 1、J-1)&& S [I] == Sは、[J])は、すべての上の文字のそれぞれ外側に拡張、3、5の長さ、およびすべての奇数長の両側を探し出します。同様に、偶数長さ6の式を使用して2 P [I、I + 1]初期パリンドローム配列の長さは、4の長さは、全てが全て探し出しなります。
public static String longestPalindrome(String s) {
int sLen = s.length();
int maxLen = 0;
String ans = "";
boolean[][] P = new boolean[sLen][sLen];
// 遍历所有长度
for (int len = 1; len <= sLen; len++) {
for (int start = 0; start < sLen; start++) {
int end = start + len - 1;
// 下标越界,结束循环
if (end >=sLen) {
break;
}
P[start][end] = (len == 1 || len == 2 || P[start + 1][end - 1]) && s.charAt(start) == s.charAt(end);
if (P[start][end] && len > maxLen) {
maxLen = len;
ans = s.substring(start, end + 1);
}
}
}
return ans;
}
時間の複雑さ:2サイクルO(n²)。
空間複雑:各サブストリングPPケースO(n²)を有する2次元アレイを節約。
例えば「babad」)にスペース使用:(以下の分析
我々は、サブストリングのケース5の長さを見つけたとき、実際にのみケース4の長さ、及び1及び2の長さと、実際には、もはや必要ストリング3を使用します。
しかし、我々は添字P配列で行われていないサイクルのために、シンクタンクを最適化する方法はありません。
私たちはアイデアを、同じ式の種類を変更するよう:
実際には、我々は最初に、我々は唯一のライン上に後方横断する必要があるので、私+1は、私を知っている知っている、漸化式から見ることができます。
public static String longestPalindrome(String s) {
int sLen = s.length();
String ans = "";
boolean[][] P = new boolean[sLen][sLen];
for (int i = sLen - 1; i >= 0; i--) {
for (int j = i; j < sLen; j++) {
P[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i < 2 || P[i + 1][j - 1]);
if (P[i][j] && j - i + 1 > ans.length()) {
ans = s.substring(i, j + 1);
}
}
}
return ans;
}
時間の複雑さと空間の複雑さを変更していないと前に、私たちは宇宙の複雑さの最適化を見ることができます。
i行目では、我々は唯一のI + 1行の情報を必要なときに求め、そのためJ以前のように、J J-1の情報を必要に応じても、逆にする必要がある場合。
public static String longestPalindrome(String s) {
int sLen = s.length();
String ans = "";
boolean[] P = new boolean[sLen];
for (int i = sLen - 1; i >= 0; i--) {
for (int j = sLen - 1; j >= i; j--) {
P[j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || P[j - 1]);
if (P[j] && j - i + 1 > ans.length()) {
ans = s.substring(i, j + 1);
}
}
}
return ans;
}
時間計算:定数O(n²)。
宇宙複雑:O(n)とに縮小。
3.2センターの拡張アルゴリズム
私たちは、各サイクルの中心を選択することができるように我々は、特定のパリンドローム配列が対称であることを知って、程度の拡張のために、文字はおよそに等しいかどうかを判断します。
我々は、合計して、または拡張の先頭から2つの文字の間に、拡張文字から開始する必要がありますので、奇数と偶数列の文字列は、存在するので
N +(N-1)センター。
public static String longestPalindrome(String s) {
if (s == null || s.length() < 1) {
return "";
}
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 = Math.max(len1, len2);
if (len > end - start) {
start = i - (len-1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
public static int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return (R-1) - (L+1) + 1;
}
3.3 Manacherアルゴリズム
https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html
4.リファレンス
https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html