#5 Longest Palindromic Substring

这道题主要是有三个变量。因为要确定一个substring,就有start point和end point,这组成了两个变量。然后其次,我们至少对每个substring从头到尾loop一遍,来确定这个substring是不是palindrome,这又需要一个n。所以,如果用暴力解法的话,这道题的time complexity是O(n^3)。如果我们要用这种方法的话,我们不用记录这个string,只需要用start point和end point两个index来记录string即可。所以暴力解法的space complexity是O(1)。

我的问题:用dynamic programming写出来了,但是依靠了hint和solution。

1. 先check input string是不是empty string,如果是empty的话,直接return空的string作为结果。

2. 创建了一个2D array来记录palindrome的长度。count[i][j] means from index i to index j (included). 如果这个区间范围只有一个数字的话,把count array里的内容initialize成1,因为一个数字它本身就是palindrome。如果区间范围大于一个数字的话,就把count array里的内容initialize成0,先把default设成没有palindrome。

3. 然后用一个nested loop来确定palindrome。According to dynamic programming, we need to find both base case and indective steps. 

Here, we have two base cases, the first is for one character, the character itself is a palindrome. The other base case is for two characters, and they are the same, like "bb".

As for inductive steps, count[i][j] = count[i+1][j-1] if count[i+1][j-1] is a palindrome and input.charAt(i) == input.charAt(j).

4. One important thing to note: since we care about count[i+1][j-1] before we need to care about count[i][j], we need to calculate count[i+1][j-1] first. Therefore, we need to calculate i from s.length() - 1 to 0, rather than from 0 to s.length() - 1

我的参考代码:

 1 class Solution {
 2     public String longestPalindrome(String s) {
 3         if(s.length() == 0){
 4             return "";
 5         }
 6         
 7         int[][] count = new int[s.length()][s.length()];
 8         for(int i = 0; i < s.length(); i++){
 9             for(int j = 0; j < s.length(); j++){
10                 if(i == j){
11                    count[i][j] = 1; 
12                 }else{
13                    count[i][j] = 0; 
14                 }
15                 
16             }
17         }
18         
19         int max = 1;
20         String maxS = s.charAt(0) + "";
21         for(int i = s.length() - 1; i >= 0; i--){
22             for(int j = i; j < s.length(); j++){
23                 if(s.charAt(i) == s.charAt(j)){
24                     if(i + 1 == j){
25                         count[i][j] = count[i][j-1] + 1;
26                     }else if(i == j){
27                         count[i][j] = 1;
28                     }else if(count[i+1][j-1] != 0){
29                         count[i][j] = count[i+1][j-1] + 2;
30                     }
31                     
32                     if(count[i][j] > max){
33                         max = count[i][j];
34                         maxS = s.substring(i, j+1);
35                     }
36                 }
37             }
38         }
39         return maxS;
40     }
41 }

另外一种dynamic programming的方法:

相比于我的方法,这个方法把2D array用来记录boolean value。然后这个方法只有18行(超级短,是我的方法的一半)。但是,对于我现在的情况而言,代码的简洁固然重要,不过对我来说,代码本身是否能跑 > 代码的效率 > 代码的可读性 > 代码的短。这个只作为参考。然后下面是我对这个方法的分析:

1. 先建了一个储存boolean value的2D array,但是没有initialize。(这里不会出现garbage value,因为像array这样的data structure是储存在heap里面的。因为这个array是boolean,所以它有默认的值,是false。所以,如果在技术层面本身的问题方面,我们不用考虑它的initialize的问题。)

2. 然后也是用了一个nested loop。对于dp[i][j],在满足s.charAt(i) == s.charAt(j),并且 i和j指向同一个 或者 i和j是相邻 或者 dp[i+1][j-1]是palindrome的情况下,把dp[i][j]设置成true。

3. 在loop里,如果当前格子是palindrome,并且当前的string长度大于之前存的string长度,把string替换成当前长度。

4. 等loop完之后,return 所储存的最长的palindrome。

参考代码:

 1 public String longestPalindrome(String s) {
 2   int n = s.length();
 3   String res = null;
 4     
 5   boolean[][] dp = new boolean[n][n];
 6     
 7   for (int i = n - 1; i >= 0; i--) {
 8     for (int j = i; j < n; j++) {
 9       dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 3 || dp[i + 1][j - 1]);
10             
11       if (dp[i][j] && (res == null || j - i + 1 > res.length())) {
12         res = s.substring(i, j + 1);
13       }
14     }
15   }
16     
17   return res;
18 }

猜你喜欢

转载自www.cnblogs.com/yxcindy/p/9944518.html