題目連接:https://leetcode.com/problems/longest-palindromic-substring/description/數組
題目大意:找出最長迴文子字符串(連續)。ide
法一:暴力,三層for循環,超時。代碼以下:spa
1 public String longestPalindrome(String s) { 2 String res = ""; 3 //逐一檢查每一個子字符串 4 for(int i = 0; i < s.length(); i++) { 5 for(int j = i + 1; j < s.length(); j++) { 6 String tmp = s.substring(i, j + 1); 7 if(isPalindrome(tmp) == true) { 8 if(tmp.length() > res.length()) { 9 res = tmp; 10 } 11 } 12 } 13 } 14 if(res.length() == 0) { 15 res = String.valueOf(s.charAt(0)); 16 } 17 return res; 18 } 19 //判斷子字符串是不是迴文 20 public static boolean isPalindrome(String s) { 21 for(int i = 0, j = s.length() - 1; i < j; i++, j--) { 22 if(s.charAt(i) != s.charAt(j)) { 23 return false; 24 } 25 } 26 return true; 27 }
法二(借鑑):dp,依次計算長度爲1,2,3,。。。n的全部子字符串是不是迴文,只是每次計算的時候均可以直接沿用上一次計算的結果,這樣能夠不用for循環判斷,也就是減小了一層for循環。dp公式:dp[i, j]=ture表示初始下標爲i,終點下標爲j的字符串是迴文字符串,dp[i, j]=true當且僅當dp[i+1, j-1]=true。代碼以下(耗時71ms):code
1 public String longestPalindrome(String s) { 2 int length = s.length(); 3 boolean dp[][] = new boolean[length][length]; 4 int start = 0, maxLength = 1; 5 //初始化迴文長度是1-2 6 for(int i = 0; i < length; i++) { 7 dp[i][i] = true; 8 if(i < length - 1 && s.charAt(i) == s.charAt(i + 1)) { 9 dp[i][i + 1] = true; 10 start = i; 11 maxLength = 2; 12 } 13 } 14 //計算迴文長度是3-length 15 for(int strLength = 3; strLength <= length; strLength++) { 16 //計算全部長度爲strLength的字符串是不是迴文串 17 for(int i = 0; i <= length - strLength; i++) { 18 int j = i + strLength - 1;//子字符串終止位置 19 if(dp[i + 1][j - 1] == true && s.charAt(i) == s.charAt(j)) { 20 dp[i][j] = true; 21 start = i; 22 maxLength = strLength; 23 } 24 } 25 } 26 return s.substring(start, start + maxLength); 27 }
dp數組(例子:cabba計算迴文):blog
0("c") | 1("a") | 2("b") | 3("b") | 4("a") | |
0("c") | T(c) | F(ca) | F(cab) | F(cabb) | F(cabba) |
1("a") | T(a) | F(ab) | F(abb) | T(abba) | |
2("b") | T(b) | T(bb) | F(bba) | ||
3("b") | T(b) | F(ba) | |||
4("a") | T(a) |
dp數組填充順序:從左下到右上,即每個數值計算都要用到左邊,下邊,左下的數據。
ip
法三(借鑑):中心擴展法(分治法),以每一個字符爲中心,向兩邊擴展找相應的字符串是否有迴文。可是,要注意兩種狀況,一種是aba的狀況,一種是abba的狀況,兩種的擴展中心有點區別。代碼以下(耗時67ms):leetcode
1 public String longestPalindrome(String s) { 2 int length = s.length(); 3 int start = 0, maxLength = 1; 4 //aba的狀況,以i爲中心擴展 5 for(int i = 0; i < length; i++) { 6 int left = i - 1, right = i + 1; 7 while(left >= 0 && right < length && s.charAt(left) == s.charAt(right)) { 8 if(right - left + 1 > maxLength) { 9 maxLength = right - left + 1; 10 start = left; 11 } 12 left--; 13 right++; 14 } 15 } 16 //abba的狀況,以i, i+1爲中心擴展 17 for(int i = 0; i < length; i++) { 18 int left = i, right = i + 1; 19 while(left >= 0 && right < length && s.charAt(left) == s.charAt(right)) { 20 if(right - left + 1 > maxLength) { 21 maxLength = right - left + 1; 22 start = left; 23 } 24 left--; 25 right++; 26 } 27 } 28 return s.substring(start, start + maxLength); 29 }