@@ -26,6 +26,55 @@ O(n2) memory is also acceptable if you do not know how to optimize memory.
26
26
27
27
要想得知不同子序列的个数,那么我们就不能在 S 和 T 中首字符不等时简单移除 S 中的首字符了,取而代之的方法应该是先将 S 复制一份,再用移除 S 中首字符后的新字符串和 T 进行比较,这点和深搜中的剪枝函数的处理有点类似。
28
28
29
+ ### Python
30
+
31
+ ``` python
32
+ class Solution :
33
+ # @param S, T: Two string.
34
+ # @return: Count the number of distinct subsequences
35
+ def numDistinct (self , S , T ):
36
+ if S is None or T is None :
37
+ return 0
38
+ if len (S) < len (T):
39
+ return 0
40
+ if len (T) == 0 :
41
+ return 1
42
+
43
+ num = 0
44
+ for i, Si in enumerate (S):
45
+ if Si == T[0 ]:
46
+ num += self .numDistinct(S[i + 1 :], T[1 :])
47
+
48
+ return num
49
+ ```
50
+
51
+ ### C++
52
+
53
+ ``` c++
54
+ class Solution {
55
+ public:
56
+ /**
57
+ * @param S, T: Two string.
58
+ * @return : Count the number of distinct subsequences
59
+ * /
60
+ int numDistinct(string &S, string &T) {
61
+ if (S.size() < T.size()) return 0;
62
+ if (T.empty()) return 1;
63
+
64
+ int num = 0;
65
+ for (int i = 0; i < S.size(); ++i) {
66
+ if (S[ i] == T[ 0] ) {
67
+ string Si = S.substr(i + 1);
68
+ string t = T.substr(1);
69
+ num += numDistinct(Si, t);
70
+ }
71
+ }
72
+
73
+ return num;
74
+ }
75
+ };
76
+ ```
77
+
29
78
### Java
30
79
31
80
```java
@@ -54,15 +103,19 @@ public class Solution {
54
103
55
104
### 源码分析
56
105
57
- 1 . 对 null 异常处理
106
+ 1 . 对 null 异常处理(C++ 中对 string 赋NULL 是错的,函数内部无法 handle 这种情况)
58
107
2 . S 字符串长度若小于 T 字符串长度,T 必然不是 S 的子序列,返回0
59
108
3 . T 字符串长度为0,证明 T 是 S 的子序列,返回1
60
109
61
110
由于进入 for 循环的前提是 ` T.length() >= 1 ` , 故当 T 的长度为1时,Java 中对 T 取子串` T.substring(1) ` 时产生的是空串` "" ` 而并不抛出索引越界的异常。
62
111
63
112
### 复杂度分析
64
113
65
- 最好情况下,S 中没有和 T 相同的字符,时间复杂度为 $$ O(n) $$ ; 最坏情况下,S 中的字符和 T 中字符完全相同,此时可以画出递归调用栈,发现和深搜非常类似,数学关系为 $$ f(n) = \sum _{i = 1} ^{n - 1} f(i) $$ , 这是指数级别的复杂度。
114
+ 最好情况下,S 中没有和 T 相同的字符,时间复杂度为 $$ O(n) $$ ; 最坏情况下,S 中的字符和 T 中字符完全相同,此时可以画出递归调用栈,发现和深搜非常类似,数学关系为 $$ f(n) = \sum _{i = 1} ^{n - 1} f(i) $$ , 这比 Fibonacci 的复杂度还要高很多。
115
+
116
+ ## 题解2 - Dynamic Programming
117
+
118
+ 从题解1 的复杂度分析中我们能发现由于存在较多的重叠子状态(相同子串被比较多次), 因此可以想到使用动态规划优化。但是动规的三大要素如何建立?由于本题为两个字符串之间的关系,故可以尝试使用双序列动规的思路求解。
66
119
67
120
## Reference
68
121
0 commit comments