5.Longest Palindromic Substring---dp

題目連接: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     }
View Code

法二(借鑑):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     }
View Code

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     }
View Code
相關文章
相關標籤/搜索