|
52 | 52 |
|
53 | 53 | <!-- 这里可写通用的实现逻辑 -->
|
54 | 54 |
|
55 |
| -动态规划,`dp[i][j]` 表示 `s[:i]` 的子序列中 `t[:j]` 的出现次数 |
| 55 | +**方法一:动态规划** |
| 56 | + |
| 57 | +定义 `dp[i][j]` 表示 `s[0..i]` 的子序列中 `t[0..j]` 出现的个数。初始时 `dp[i][0]=1`,表示空串是任意字符串的子序列。答案为 `dp[m][n]`。 |
| 58 | + |
| 59 | +当 `s[i] == t[j]` 时,`dp[i][j] = dp[i-1][j-1] + dp[i-1][j]`,即 `s[0..i]` 的子序列中 `t[0..j]` 出现的个数等于 `s[0..i-1]` 的子序列中 `t[0..j-1]` 出现的个数加上 `s[0..i-1]` 的子序列中 `t[0..j]` 出现的个数。 |
| 60 | + |
| 61 | +当 `s[i] != t[j]` 时,`dp[i][j] = dp[i-1][j]`,即 `s[0..i]` 的子序列中 `t[0..j]` 出现的个数等于 `s[0..i-1]` 的子序列中 `t[0..j]` 出现的个数。 |
| 62 | + |
| 63 | +因此,可以得到状态转移方程: |
| 64 | + |
| 65 | +$$ |
| 66 | +dp[i][j]= |
| 67 | +\begin{cases} |
| 68 | +dp[i-1][j-1]+dp[i-1][j], & s[i]=t[j] \\ |
| 69 | +dp[i-1][j], & s[i]\neq t[j] |
| 70 | +\end{cases} |
| 71 | +$$ |
| 72 | + |
| 73 | +时间复杂度 $O(m\times n)$,空间复杂度 $O(m\times n)$。其中 $m$, $n$ 分别是字符串 `s` 和 `t` 的长度。 |
56 | 74 |
|
57 | 75 | <!-- tabs:start -->
|
58 | 76 |
|
@@ -82,15 +100,14 @@ class Solution:
|
82 | 100 | ```java
|
83 | 101 | class Solution {
|
84 | 102 | public int numDistinct(String s, String t) {
|
85 |
| - int m = s.length(); |
86 |
| - int n = t.length(); |
| 103 | + int m = s.length(), n = t.length(); |
87 | 104 | int[][] dp = new int[m + 1][n + 1];
|
88 |
| - for (int i = 0; i <= m; i++) { |
| 105 | + for (int i = 0; i <= m; ++i) { |
89 | 106 | dp[i][0] = 1;
|
90 | 107 | }
|
91 |
| - for (int i = 1; i <= m; i++) { |
92 |
| - for (int j = 1; j <= n; j++) { |
93 |
| - dp[i][j] = dp[i - 1][j]; |
| 108 | + for (int i = 1; i <= m; ++i) { |
| 109 | + for (int j = 1; j <= n; ++j) { |
| 110 | + dp[i][j] += dp[i - 1][j]; |
94 | 111 | if (s.charAt(i - 1) == t.charAt(j - 1)) {
|
95 | 112 | dp[i][j] += dp[i - 1][j - 1];
|
96 | 113 | }
|
@@ -147,6 +164,30 @@ public:
|
147 | 164 | };
|
148 | 165 | ```
|
149 | 166 |
|
| 167 | +### **TypeScript** |
| 168 | +
|
| 169 | +```ts |
| 170 | +function numDistinct(s: string, t: string): number { |
| 171 | + const m = s.length; |
| 172 | + const n = t.length; |
| 173 | + const dp: number[][] = new Array(m + 1) |
| 174 | + .fill(0) |
| 175 | + .map(() => new Array(n + 1).fill(0)); |
| 176 | + for (let i = 0; i <= m; ++i) { |
| 177 | + dp[i][0] = 1; |
| 178 | + } |
| 179 | + for (let i = 1; i <= m; ++i) { |
| 180 | + for (let j = 1; j <= n; ++j) { |
| 181 | + dp[i][j] = dp[i - 1][j]; |
| 182 | + if (s.charAt(i - 1) === t.charAt(j - 1)) { |
| 183 | + dp[i][j] += dp[i - 1][j - 1]; |
| 184 | + } |
| 185 | + } |
| 186 | + } |
| 187 | + return dp[m][n]; |
| 188 | +} |
| 189 | +``` |
| 190 | + |
150 | 191 | ### **...**
|
151 | 192 |
|
152 | 193 | ```
|
|
0 commit comments