題目描述以下:html
能馬上想到的就是爆破,先試試無腦爆破,時間複雜度O(n^3),而後毫無心外的超時了,爆破代碼以下:java
public String longestPalindrome(String s) { int max = 0; int length = s.length(); // 字符串長度只有1個或爲空,那麼它自身就是迴文串 if (length <= 1) { return s; } String rtString = ""; // 從第一個字符開始,統計以每一個字符開頭的能達到的最大回文子串 for (int i = 0; i < length; i++) { for (int j = i + 1; j < length; j++) { String subStr = s.substring(i, j + 1); int left = 0; int right = subStr.length() - 1; boolean flag = true; // 判斷是否是迴文子串 while (left <= right) { if (subStr.charAt(left) == subStr.charAt(right)) { left++; right--; }else { flag = false; break; } } int size = subStr.length(); // 進行最大長度記錄 if (flag && size > max) { max = size; rtString = subStr; } } } if (max == 0) { rtString = s.charAt(0) + ""; } return rtString; }
而後思考怎麼使用動態規劃,無奈本人動態規劃渣渣,因而看題解算法
給出定義以下數組
那麼 P(i, j)=(P(i+1,j−1) and Si==Sj) P(i,i)=true P(i, i+1) = ( S_i == S_{i+1} )P(i,i+1)=(Si==Si+1)
恍然大悟,而後開始編碼,動態規劃算法代碼以下:ide
public String longestPalindrome1(String s) { if (s.length() <= 1) { return s; } int length = s.length(); boolean[][] dp = new boolean[length][length]; // 初始化單一字符爲迴文串 for (int i = 0; i < dp.length; i++) { dp[i][i] = true; } // 由於dp[i][j]取決於d[i+1][j-1]的狀態,因此自底向上進行動態規劃 for (int i = length - 1; i >= 0; i--) { for (int j = i; j < dp[i].length; j++) { if (j - i < 2) { //兩個字符相鄰或者就是同一個字符 dp[i][j] = (s.charAt(i) == s.charAt(j)); }else { // 字符 i~j 是否爲迴文取決於 i+1 ~ j-1是否爲迴文 及 s[i] 是否等於 s[j] dp[i][j] = (dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j)); } } } // 遍歷dp數組找到最長迴文串 int maxlength = 0; int maxi = 0; int maxy = 0; for (int i = 0; i < dp.length; i++) { for (int j = i; j < dp.length; j++) { if (dp[i][j]) { int len = j - i + 1; if (len > maxlength) { maxlength = len; maxi = i; maxy = j; } } } } return s.substring(maxi, maxy + 1); }
繼續看看還有什麼算法,看到中心擴展法,即以某個字符爲中心向兩邊擴展,時間複雜度爲O(n^2)代碼以下:編碼
public String longestPalindrome2(String s) { int length = s.length(); if (length <= 1) { return s; } int max = 0; int startIndex = 0; // 這輪循環時計算 for (int i = 0; i < length; i++) { int left = i; int right = i; // 求得迴文串長度爲奇數的串,返回值爲{迴文串串長度,迴文串開始下標} int[] jiCuan = getCuan(s, left, right); // 求得迴文串長度爲偶數的串,返回值爲{迴文串串長度,迴文串開始下標} int[] ouCuan = getCuan(s, left, right + 1); int bigger = 0; if (jiCuan[0] > ouCuan[0]) { bigger = jiCuan[0]; left = jiCuan[1]; }else { bigger = ouCuan[0]; left = ouCuan[1]; } if (bigger > max) { max = bigger; startIndex = left; } } return s.substring(startIndex, startIndex + max); } public int[] getCuan(String s, int left, int right) { // s[left](奇數迴文串時)或s[left]~s[right](偶數迴文串時)爲中心向兩邊擴展 while (left >= 0 && right < s.length()) { if (s.charAt(left) == s.charAt(right)) { left--; right++; }else { break; } } // 循環退出以前會把left-1,right+1,因此分別要加回來和減出去 left = left + 1; right = right - 1; int[] a = {right - left + 1, left}; return a; }
還有一種算法,比較難想到,時間複雜度爲O(n),人稱「馬拉車算法」,這裏給出參考連接:spa
https://www.cnblogs.com/grandyang/p/4475985.html3d