————2020.1.16————

# 算法 || 记一次递归到dp优化实例 #


# *leetcode 115

 

1、暴力递归(Java)

 1 public class Solutions {
 2 public static int numDistinct(String s, String t) {
 3         return dfs (s,t,0,"");
 4     }
 5 
 6 public static int dfs(String s, String t, int index, String cur) {
 7     if (index == s.length()) {
 8         return cur.equals(t) ? 1 : 0;
 9     }
10     return dfs(s, t, index+1, cur + s.charAt(index)) + dfs(s, t, index+1, cur);
11 }
12     public static void main(String[] args) {
13         String s = "rabbbbbbbbbbbbiiiiiiit";
14         String t = "rabbit";
15         System.out.println(numDistinct(s,t));
16     }
17 }

长串显然超时(此样例用时1437ms)。

2、记忆化搜索(Java)

 1 import java.util.HashMap;
 2 
 3 public class Solutions {
 4     static class Returntype{
 5         public int index;
 6         public String cur;
 7         public Returntype(int index, String cur) {
 8             this.cur = cur;
 9             this.index = index;
10         }
11     }
12     static HashMap<Returntype,Integer> map = new HashMap<>();
13     public static int numDistinct(String s, String t) {
14             return dfs (s,t,0,"");
15         }
16     public static int dfs(String s, String t, int index, String cur) {
17         if (index == s.length()) {
18             return cur.equals(t) ? 1 : 0;
19         }
20         Returntype yes = new Returntype(index+1,cur + s.charAt(index));
21         Returntype no = new Returntype(index+1,cur);
22         int yeS = map.containsKey(yes) ? map.get(yes) : dfs(s, t, index+1, cur + s.charAt(index));
23         int nO = map.containsKey(no) ? map.get(no) : dfs(s, t, index+1, cur);
24         map.put(new Returntype(index,cur),yeS+nO);
25         return yeS + nO;
26     }
27     public static void main(String[] args) {
28         String s = "rabbbbbbbbbbbbiiiiiiit ";
29                 String t = "rabbit";
30         long startTime = System.currentTimeMillis(); 
31         System.out.println(numDistinct(s,t));
32         long endTime = System.currentTimeMillis(); 
33         System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
34     }
35 }
扫描二维码关注公众号,回复: 8650025 查看本文章

也许是姿势不对,用时居然比暴力递归还要长(递归思路貌似也和其他人不太一样),具体之后再研究,总之仍然超时。(几万ms)

3、二维动态规划(Java)

终于意识到自己递归的麻烦所在(状态不好表示,其中一个维度即curString量级为指数且要将s所有情况枚举),故改用他人思路,分别用i,j表示匹配到s、t的当前位置。

易得出转移方程为 dp[i][j] = s.charAt(i) == t.charAt(j) ? dp[i-1][j-1] + dp[i-1][j] : dp[i-1][j]

 1 public static int numDistinct(String s, String t) {
 2         int[][] dp = new int[s.length()+1][t.length()+1];
 3             for(int i =0;i<=s.length();i++) dp[i][0] = 1;
 4             for(int i = 1;i<=s.length();i++) {
 5                 for(int j = 1;j<=t.length();j++) {
 6                     dp[i][j] = s.charAt(i-1) == t.charAt(j-1) ? dp[i-1][j-1] + dp[i-1][j] : dp[i-1][j];
 7                 }
 8             }
 9             return dp[s.length()][t.length()];
10      }

同样的样例时间为1ms,效率显著提高。

4、一维动态规划(Java)

继续从空间角度进行优化。

 1 public static int numDistinct(String s, String t) {
 2         int m = s.length(), n = t.length();
 3         int dp[] = new int[n+1];
 4         int pre = 0, tmp;
 5         for(int i = 0; i <= m; i++)
 6             for(int j = 0; j <= n; j++)
 7             {
 8                 tmp = dp[j];
 9                 if(j == 0) dp[j] = 1;
10                 else if(i == 0) dp[j] = 0;
11                 else if(s.charAt(i-1) == t.charAt(j-1)) dp[j] += pre;
12                 pre = tmp;
13             }
14         return dp[n];
15      }

# Edit : 2020.1.15 

猜你喜欢

转载自www.cnblogs.com/zzl1209/p/12203729.html
今日推荐