Skip to content

Commit daff7e9

Browse files
committed
add Python and C++ implementation
1 parent c04f0c4 commit daff7e9

File tree

1 file changed

+55
-2
lines changed

1 file changed

+55
-2
lines changed

dynamic_programming/distinct_subsequences.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,55 @@ O(n2) memory is also acceptable if you do not know how to optimize memory.
2626

2727
要想得知不同子序列的个数,那么我们就不能在 S 和 T 中首字符不等时简单移除 S 中的首字符了,取而代之的方法应该是先将 S 复制一份,再用移除 S 中首字符后的新字符串和 T 进行比较,这点和深搜中的剪枝函数的处理有点类似。
2828

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+
2978
### Java
3079
3180
```java
@@ -54,15 +103,19 @@ public class Solution {
54103

55104
### 源码分析
56105

57-
1. 对 null 异常处理
106+
1. 对 null 异常处理(C++ 中对 string 赋NULL 是错的,函数内部无法 handle 这种情况)
58107
2. S 字符串长度若小于 T 字符串长度,T 必然不是 S 的子序列,返回0
59108
3. T 字符串长度为0,证明 T 是 S 的子序列,返回1
60109

61110
由于进入 for 循环的前提是 `T.length() >= 1`, 故当 T 的长度为1时,Java 中对 T 取子串`T.substring(1)`时产生的是空串`""`而并不抛出索引越界的异常。
62111

63112
### 复杂度分析
64113

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 的复杂度分析中我们能发现由于存在较多的重叠子状态(相同子串被比较多次), 因此可以想到使用动态规划优化。但是动规的三大要素如何建立?由于本题为两个字符串之间的关系,故可以尝试使用双序列动规的思路求解。
66119

67120
## Reference
68121

0 commit comments

Comments
 (0)