From 0d7ca4cb2412396a019dbca97e0d69afb5431be2 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Mon, 21 Aug 2023 16:06:15 +0800 Subject: [PATCH] feat: add solutions to lc/lcof2 problems: Distinct Subsequences lc No.0115 & lcof2 No.097 --- .../README.md" | 219 +++++++++++++--- .../Solution.cpp" | 37 ++- .../Solution.go" | 20 +- .../Solution.java" | 35 ++- .../Solution.py" | 21 +- .../Solution.ts" | 14 + .../0115.Distinct Subsequences/README.md | 240 ++++++++++++------ .../0115.Distinct Subsequences/README_EN.md | 206 +++++++++++---- .../0115.Distinct Subsequences/Solution.cpp | 35 ++- .../0115.Distinct Subsequences/Solution.go | 20 +- .../0115.Distinct Subsequences/Solution.java | 32 ++- .../0115.Distinct Subsequences/Solution.py | 21 +- .../0115.Distinct Subsequences/Solution.ts | 21 +- 13 files changed, 624 insertions(+), 297 deletions(-) create mode 100644 "lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.ts" diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/README.md" "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/README.md" index f143d7d59b50e..8ce21650b2f58 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/README.md" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/README.md" @@ -54,7 +54,31 @@ -动态规划,`dp[i][j]` 表示 `s[:i]` 的子序列中 `t[:j]` 的出现次数 +**方法一:动态规划** + +我们定义 $f[i][j]$ 表示字符串 $s$ 的前 $i$ 个字符中,子序列构成字符串 $t$ 的前 $j$ 个字符的方案数。初始时 $f[i][0]=1$,其中 $i \in [0,m]$。 + +当 $i \gt 0$ 时,考虑 $f[i][j]$ 的计算: + +- 当 $s[i-1] \ne t[j-1]$ 时,不能选取 $s[i-1]$,因此 $f[i][j]=f[i-1][j]$; +- 否则,可以选取 $s[i-1]$,此时 $f[i][j]=f[i-1][j-1]$。 + +因此我们有如下的状态转移方程: + +$$ +f[i][j]=\left\{ +\begin{aligned} +&f[i-1][j], &s[i-1] \ne t[j-1] \\ +&f[i-1][j-1]+f[i-1][j], &s[i-1]=t[j-1] +\end{aligned} +\right. +$$ + +最终的答案即为 $f[m][n]$,其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。 + +我们注意到 $f[i][j]$ 的计算只和 $f[i-1][..]$ 有关,因此,我们可以优化掉第一维,这样空间复杂度可以降低到 $O(n)$。 @@ -66,15 +90,27 @@ class Solution: def numDistinct(self, s: str, t: str) -> int: m, n = len(s), len(t) - dp = [[0] * (n + 1) for _ in range(m + 1)] + f = [[0] * (n + 1) for _ in range(m + 1)] for i in range(m + 1): - dp[i][0] = 1 - for i in range(1, m + 1): - for j in range(1, n + 1): - dp[i][j] = dp[i - 1][j] - if s[i - 1] == t[j - 1]: - dp[i][j] += dp[i - 1][j - 1] - return dp[m][n] + f[i][0] = 1 + for i, a in enumerate(s, 1): + for j, b in enumerate(t, 1): + f[i][j] = f[i - 1][j] + if a == b: + f[i][j] += f[i - 1][j - 1] + return f[m][n] +``` + +```python +class Solution: + def numDistinct(self, s: str, t: str) -> int: + n = len(t) + f = [1] + [0] * n + for a in s: + for j in range(n, 0, -1): + if a == t[j - 1]: + f[j] += f[j - 1] + return f[n] ``` ### **Java** @@ -84,69 +120,168 @@ class Solution: ```java class Solution { public int numDistinct(String s, String t) { - int m = s.length(); - int n = t.length(); - int[][] dp = new int[m + 1][n + 1]; - for (int i = 0; i <= m; i++) { - dp[i][0] = 1; + int m = s.length(), n = t.length(); + int[][] f = new int[m + 1][n + 1]; + for (int i = 0; i < m + 1; ++i) { + f[i][0] = 1; } - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { - dp[i][j] = dp[i - 1][j]; + for (int i = 1; i < m + 1; ++i) { + for (int j = 1; j < n + 1; ++j) { + f[i][j] = f[i - 1][j]; if (s.charAt(i - 1) == t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; + f[i][j] += f[i - 1][j - 1]; + } + } + } + return f[m][n]; + } +} +``` + +```java +class Solution { + public int numDistinct(String s, String t) { + int n = t.length(); + int[] f = new int[n + 1]; + f[0] = 1; + for (char a : s.toCharArray()) { + for (int j = n; j > 0; --j) { + char b = t.charAt(j - 1); + if (a == b) { + f[j] += f[j - 1]; } } } - return dp[m][n]; + return f[n]; } } ``` +### **C++** + +```cpp +class Solution { +public: + int numDistinct(string s, string t) { + int m = s.size(), n = t.size(); + unsigned long long f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); + for (int i = 0; i < m + 1; ++i) { + f[i][0] = 1; + } + for (int i = 1; i < m + 1; ++i) { + for (int j = 1; j < n + 1; ++j) { + f[i][j] = f[i - 1][j]; + if (s[i - 1] == t[j - 1]) { + f[i][j] += f[i - 1][j - 1]; + } + } + } + return f[m][n]; + } +}; +``` + +```cpp +class Solution { +public: + int numDistinct(string s, string t) { + int n = t.size(); + unsigned long long f[n + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (char& a : s) { + for (int j = n; j; --j) { + char b = t[j - 1]; + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; + } +}; +``` + ### **Go** ```go func numDistinct(s string, t string) int { m, n := len(s), len(t) - dp := make([][]int, m+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) + } for i := 0; i <= m; i++ { - dp[i] = make([]int, n+1) - dp[i][0] = 1 + f[i][0] = 1 } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { - dp[i][j] = dp[i-1][j] + f[i][j] = f[i-1][j] if s[i-1] == t[j-1] { - dp[i][j] += dp[i-1][j-1] + f[i][j] += f[i-1][j-1] } } } - return dp[m][n] + return f[m][n] } ``` -### **C++** +```go +func numDistinct(s string, t string) int { + n := len(t) + f := make([]int, n+1) + f[0] = 1 + for _, a := range s { + for j := n; j > 0; j-- { + if b := t[j-1]; byte(a) == b { + f[j] += f[j-1] + } + } + } + return f[n] +} +``` -```cpp -class Solution { -public: - int numDistinct(string s, string t) { - int m = s.size(), n = t.size(); - vector> dp(m + 1, vector(n + 1)); - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; +### **TypeScript** + +```ts +function numDistinct(s: string, t: string): number { + const m = s.length; + const n = t.length; + const f: number[][] = new Array(m + 1) + .fill(0) + .map(() => new Array(n + 1).fill(0)); + for (let i = 0; i <= m; ++i) { + f[i][0] = 1; + } + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + f[i][j] = f[i - 1][j]; + if (s[i - 1] === t[j - 1]) { + f[i][j] += f[i - 1][j - 1]; + } } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; - if (s[i - 1] == t[j - 1]) { - dp[i][j] += dp[i - 1][j - 1]; - } + } + return f[m][n]; +} +``` + +```ts +function numDistinct(s: string, t: string): number { + const n = t.length; + const f: number[] = new Array(n + 1).fill(0); + f[0] = 1; + for (const a of s) { + for (let j = n; j; --j) { + const b = t[j - 1]; + if (a === b) { + f[j] += f[j - 1]; } } - return dp[m][n]; } -}; + return f[n]; +} ``` ### **...** diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.cpp" "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.cpp" index 1123a080aba18..eff3166f6e6e6 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.cpp" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.cpp" @@ -1,19 +1,18 @@ -class Solution { -public: - int numDistinct(string s, string t) { - int m = s.size(), n = t.size(); - vector> dp(m + 1, vector(n + 1)); - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; - } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; - if (s[i - 1] == t[j - 1]) { - dp[i][j] += dp[i - 1][j - 1]; - } - } - } - return dp[m][n]; - } -}; +class Solution { +public: + int numDistinct(string s, string t) { + int n = t.size(); + unsigned long long f[n + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (char& a : s) { + for (int j = n; j; --j) { + char b = t[j - 1]; + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; + } +}; \ No newline at end of file diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.go" "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.go" index 14555730d2ed9..3b1eed97f2db4 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.go" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.go" @@ -1,17 +1,13 @@ func numDistinct(s string, t string) int { - m, n := len(s), len(t) - dp := make([][]int, m+1) - for i := 0; i <= m; i++ { - dp[i] = make([]int, n+1) - dp[i][0] = 1 - } - for i := 1; i <= m; i++ { - for j := 1; j <= n; j++ { - dp[i][j] = dp[i-1][j] - if s[i-1] == t[j-1] { - dp[i][j] += dp[i-1][j-1] + n := len(t) + f := make([]int, n+1) + f[0] = 1 + for _, a := range s { + for j := n; j > 0; j-- { + if b := t[j-1]; byte(a) == b { + f[j] += f[j-1] } } } - return dp[m][n] + return f[n] } \ No newline at end of file diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.java" "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.java" index ee2383f04017c..0c90de4f2d637 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.java" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.java" @@ -1,19 +1,16 @@ -class Solution { - public int numDistinct(String s, String t) { - int m = s.length(); - int n = t.length(); - int[][] dp = new int[m + 1][n + 1]; - for (int i = 0; i <= m; i++) { - dp[i][0] = 1; - } - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { - dp[i][j] = dp[i - 1][j]; - if (s.charAt(i - 1) == t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; - } - } - } - return dp[m][n]; - } -} +class Solution { + public int numDistinct(String s, String t) { + int n = t.length(); + int[] f = new int[n + 1]; + f[0] = 1; + for (char a : s.toCharArray()) { + for (int j = n; j > 0; --j) { + char b = t.charAt(j - 1); + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; + } +} \ No newline at end of file diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.py" "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.py" index b347109898491..9e7e02af1363e 100644 --- "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.py" +++ "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.py" @@ -1,12 +1,9 @@ -class Solution: - def numDistinct(self, s: str, t: str) -> int: - m, n = len(s), len(t) - dp = [[0] * n + 1 for _ in range(m + 1)] - for i in range(m + 1): - dp[i][0] = 1 - for i in range(1, m + 1): - for j in range(1, n + 1): - dp[i][j] = dp[i - 1][j] - if s[i - 1] == s[j - 1]: - dp[i][j] += dp[i - 1][j - 1] - return dp[m][n] +class Solution: + def numDistinct(self, s: str, t: str) -> int: + n = len(t) + f = [1] + [0] * n + for a in s: + for j in range(n, 0, -1): + if a == t[j - 1]: + f[j] += f[j - 1] + return f[n] diff --git "a/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.ts" "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.ts" new file mode 100644 index 0000000000000..f254f30e9f3f8 --- /dev/null +++ "b/lcof2/\345\211\221\346\214\207 Offer II 097. \345\255\220\345\272\217\345\210\227\347\232\204\346\225\260\347\233\256/Solution.ts" @@ -0,0 +1,14 @@ +function numDistinct(s: string, t: string): number { + const n = t.length; + const f: number[] = new Array(n + 1).fill(0); + f[0] = 1; + for (const a of s) { + for (let j = n; j; --j) { + const b = t[j - 1]; + if (a === b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; +} diff --git a/solution/0100-0199/0115.Distinct Subsequences/README.md b/solution/0100-0199/0115.Distinct Subsequences/README.md index 3dc022f6d1756..0d8f2351e8abc 100644 --- a/solution/0100-0199/0115.Distinct Subsequences/README.md +++ b/solution/0100-0199/0115.Distinct Subsequences/README.md @@ -52,23 +52,29 @@ babgbag **方法一:动态规划** -定义 `dp[i][j]` 表示 `s[0..i]` 的子序列中 `t[0..j]` 出现的个数。初始时 `dp[i][0]=1`,表示空串是任意字符串的子序列。答案为 `dp[m][n]`。 +我们定义 $f[i][j]$ 表示字符串 $s$ 的前 $i$ 个字符中,子序列构成字符串 $t$ 的前 $j$ 个字符的方案数。初始时 $f[i][0]=1$,其中 $i \in [0,m]$。 -当 `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]` 出现的个数。 +当 $i \gt 0$ 时,考虑 $f[i][j]$ 的计算: -当 `s[i] != t[j]` 时,`dp[i][j] = dp[i-1][j]`,即 `s[0..i]` 的子序列中 `t[0..j]` 出现的个数等于 `s[0..i-1]` 的子序列中 `t[0..j]` 出现的个数。 +- 当 $s[i-1] \ne t[j-1]$ 时,不能选取 $s[i-1]$,因此 $f[i][j]=f[i-1][j]$; +- 否则,可以选取 $s[i-1]$,此时 $f[i][j]=f[i-1][j-1]$。 -因此,可以得到状态转移方程: +因此我们有如下的状态转移方程: $$ -dp[i][j]= -\begin{cases} -dp[i-1][j-1]+dp[i-1][j], & s[i]=t[j] \\ -dp[i-1][j], & s[i]\neq t[j] -\end{cases} +f[i][j]=\left\{ +\begin{aligned} +&f[i-1][j], &s[i-1] \ne t[j-1] \\ +&f[i-1][j-1]+f[i-1][j], &s[i-1]=t[j-1] +\end{aligned} +\right. $$ -时间复杂度 $O(m\times n)$,空间复杂度 $O(m\times n)$。其中 $m$, $n$ 分别是字符串 `s` 和 `t` 的长度。 +最终的答案即为 $f[m][n]$,其中 $m$ 和 $n$ 分别是字符串 $s$ 和 $t$ 的长度。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。 + +我们注意到 $f[i][j]$ 的计算只和 $f[i-1][..]$ 有关,因此,我们可以优化掉第一维,这样空间复杂度可以降低到 $O(n)$。 @@ -80,15 +86,27 @@ $$ class Solution: def numDistinct(self, s: str, t: str) -> int: m, n = len(s), len(t) - dp = [[0] * (n + 1) for _ in range(m + 1)] + f = [[0] * (n + 1) for _ in range(m + 1)] for i in range(m + 1): - dp[i][0] = 1 - for i in range(1, m + 1): - for j in range(1, n + 1): - dp[i][j] = dp[i - 1][j] - if s[i - 1] == t[j - 1]: - dp[i][j] += dp[i - 1][j - 1] - return dp[m][n] + f[i][0] = 1 + for i, a in enumerate(s, 1): + for j, b in enumerate(t, 1): + f[i][j] = f[i - 1][j] + if a == b: + f[i][j] += f[i - 1][j - 1] + return f[m][n] +``` + +```python +class Solution: + def numDistinct(self, s: str, t: str) -> int: + n = len(t) + f = [1] + [0] * n + for a in s: + for j in range(n, 0, -1): + if a == t[j - 1]: + f[j] += f[j - 1] + return f[n] ``` ### **Java** @@ -99,67 +117,167 @@ class Solution: class Solution { public int numDistinct(String s, String t) { int m = s.length(), n = t.length(); - int[][] dp = new int[m + 1][n + 1]; - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; + int[][] f = new int[m + 1][n + 1]; + for (int i = 0; i < m + 1; ++i) { + f[i][0] = 1; } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] += dp[i - 1][j]; + for (int i = 1; i < m + 1; ++i) { + for (int j = 1; j < n + 1; ++j) { + f[i][j] = f[i - 1][j]; if (s.charAt(i - 1) == t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; + f[i][j] += f[i - 1][j - 1]; + } + } + } + return f[m][n]; + } +} +``` + +```java +class Solution { + public int numDistinct(String s, String t) { + int n = t.length(); + int[] f = new int[n + 1]; + f[0] = 1; + for (char a : s.toCharArray()) { + for (int j = n; j > 0; --j) { + char b = t.charAt(j - 1); + if (a == b) { + f[j] += f[j - 1]; } } } - return dp[m][n]; + return f[n]; } } ``` +### **C++** + +```cpp +class Solution { +public: + int numDistinct(string s, string t) { + int m = s.size(), n = t.size(); + unsigned long long f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); + for (int i = 0; i < m + 1; ++i) { + f[i][0] = 1; + } + for (int i = 1; i < m + 1; ++i) { + for (int j = 1; j < n + 1; ++j) { + f[i][j] = f[i - 1][j]; + if (s[i - 1] == t[j - 1]) { + f[i][j] += f[i - 1][j - 1]; + } + } + } + return f[m][n]; + } +}; +``` + +```cpp +class Solution { +public: + int numDistinct(string s, string t) { + int n = t.size(); + unsigned long long f[n + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (char& a : s) { + for (int j = n; j; --j) { + char b = t[j - 1]; + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; + } +}; +``` + ### **Go** ```go func numDistinct(s string, t string) int { m, n := len(s), len(t) - dp := make([][]int, m+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) + } for i := 0; i <= m; i++ { - dp[i] = make([]int, n+1) - dp[i][0] = 1 + f[i][0] = 1 } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { - dp[i][j] = dp[i-1][j] + f[i][j] = f[i-1][j] if s[i-1] == t[j-1] { - dp[i][j] += dp[i-1][j-1] + f[i][j] += f[i-1][j-1] } } } - return dp[m][n] + return f[m][n] } ``` -### **C++** +```go +func numDistinct(s string, t string) int { + n := len(t) + f := make([]int, n+1) + f[0] = 1 + for _, a := range s { + for j := n; j > 0; j-- { + if b := t[j-1]; byte(a) == b { + f[j] += f[j-1] + } + } + } + return f[n] +} +``` -```cpp -class Solution { -public: - int numDistinct(string s, string t) { - int m = s.size(), n = t.size(); - vector> dp(m + 1, vector(n + 1)); - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; +### **TypeScript** + +```ts +function numDistinct(s: string, t: string): number { + const m = s.length; + const n = t.length; + const f: number[][] = new Array(m + 1) + .fill(0) + .map(() => new Array(n + 1).fill(0)); + for (let i = 0; i <= m; ++i) { + f[i][0] = 1; + } + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + f[i][j] = f[i - 1][j]; + if (s[i - 1] === t[j - 1]) { + f[i][j] += f[i - 1][j - 1]; + } } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; - if (s[i - 1] == t[j - 1]) { - dp[i][j] += dp[i - 1][j - 1]; - } + } + return f[m][n]; +} +``` + +```ts +function numDistinct(s: string, t: string): number { + const n = t.length; + const f: number[] = new Array(n + 1).fill(0); + f[0] = 1; + for (const a of s) { + for (let j = n; j; --j) { + const b = t[j - 1]; + if (a === b) { + f[j] += f[j - 1]; } } - return dp[m][n]; } -}; + return f[n]; +} ``` ### **Rust** @@ -193,30 +311,6 @@ impl Solution { } ``` -### **TypeScript** - -```ts -function numDistinct(s: string, t: string): number { - const m = s.length; - const n = t.length; - const dp: number[][] = new Array(m + 1) - .fill(0) - .map(() => new Array(n + 1).fill(0)); - for (let i = 0; i <= m; ++i) { - dp[i][0] = 1; - } - for (let i = 1; i <= m; ++i) { - for (let j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; - if (s.charAt(i - 1) === t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; - } - } - } - return dp[m][n]; -} -``` - ### **...** ``` diff --git a/solution/0100-0199/0115.Distinct Subsequences/README_EN.md b/solution/0100-0199/0115.Distinct Subsequences/README_EN.md index 0391d9d1f11c9..4c9029307806f 100644 --- a/solution/0100-0199/0115.Distinct Subsequences/README_EN.md +++ b/solution/0100-0199/0115.Distinct Subsequences/README_EN.md @@ -52,15 +52,27 @@ As shown below, there are 5 ways you can generate "bag" from s. class Solution: def numDistinct(self, s: str, t: str) -> int: m, n = len(s), len(t) - dp = [[0] * (n + 1) for _ in range(m + 1)] + f = [[0] * (n + 1) for _ in range(m + 1)] for i in range(m + 1): - dp[i][0] = 1 - for i in range(1, m + 1): - for j in range(1, n + 1): - dp[i][j] = dp[i - 1][j] - if s[i - 1] == t[j - 1]: - dp[i][j] += dp[i - 1][j - 1] - return dp[m][n] + f[i][0] = 1 + for i, a in enumerate(s, 1): + for j, b in enumerate(t, 1): + f[i][j] = f[i - 1][j] + if a == b: + f[i][j] += f[i - 1][j - 1] + return f[m][n] +``` + +```python +class Solution: + def numDistinct(self, s: str, t: str) -> int: + n = len(t) + f = [1] + [0] * n + for a in s: + for j in range(n, 0, -1): + if a == t[j - 1]: + f[j] += f[j - 1] + return f[n] ``` ### **Java** @@ -69,19 +81,38 @@ class Solution: class Solution { public int numDistinct(String s, String t) { int m = s.length(), n = t.length(); - int[][] dp = new int[m + 1][n + 1]; - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; + int[][] f = new int[m + 1][n + 1]; + for (int i = 0; i < m + 1; ++i) { + f[i][0] = 1; } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] += dp[i - 1][j]; + for (int i = 1; i < m + 1; ++i) { + for (int j = 1; j < n + 1; ++j) { + f[i][j] = f[i - 1][j]; if (s.charAt(i - 1) == t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; + f[i][j] += f[i - 1][j - 1]; } } } - return dp[m][n]; + return f[m][n]; + } +} +``` + +```java +class Solution { + public int numDistinct(String s, String t) { + int n = t.length(); + int[] f = new int[n + 1]; + f[0] = 1; + for (char a : s.toCharArray()) { + for (int j = n; j > 0; --j) { + char b = t.charAt(j - 1); + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; } } ``` @@ -115,23 +146,126 @@ class Solution { public: int numDistinct(string s, string t) { int m = s.size(), n = t.size(); - vector> dp(m + 1, vector(n + 1)); - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; + unsigned long long f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); + for (int i = 0; i < m + 1; ++i) { + f[i][0] = 1; } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; + for (int i = 1; i < m + 1; ++i) { + for (int j = 1; j < n + 1; ++j) { + f[i][j] = f[i - 1][j]; if (s[i - 1] == t[j - 1]) { - dp[i][j] += dp[i - 1][j - 1]; + f[i][j] += f[i - 1][j - 1]; } } } - return dp[m][n]; + return f[m][n]; } }; ``` +```cpp +class Solution { +public: + int numDistinct(string s, string t) { + int n = t.size(); + unsigned long long f[n + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (char& a : s) { + for (int j = n; j; --j) { + char b = t[j - 1]; + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; + } +}; +``` + +### **Go** + +```go +func numDistinct(s string, t string) int { + m, n := len(s), len(t) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) + } + for i := 0; i <= m; i++ { + f[i][0] = 1 + } + for i := 1; i <= m; i++ { + for j := 1; j <= n; j++ { + f[i][j] = f[i-1][j] + if s[i-1] == t[j-1] { + f[i][j] += f[i-1][j-1] + } + } + } + return f[m][n] +} +``` + +```go +func numDistinct(s string, t string) int { + n := len(t) + f := make([]int, n+1) + f[0] = 1 + for _, a := range s { + for j := n; j > 0; j-- { + if b := t[j-1]; byte(a) == b { + f[j] += f[j-1] + } + } + } + return f[n] +} +``` + +### **TypeScript** + +```ts +function numDistinct(s: string, t: string): number { + const m = s.length; + const n = t.length; + const f: number[][] = new Array(m + 1) + .fill(0) + .map(() => new Array(n + 1).fill(0)); + for (let i = 0; i <= m; ++i) { + f[i][0] = 1; + } + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + f[i][j] = f[i - 1][j]; + if (s[i - 1] === t[j - 1]) { + f[i][j] += f[i - 1][j - 1]; + } + } + } + return f[m][n]; +} +``` + +```ts +function numDistinct(s: string, t: string): number { + const n = t.length; + const f: number[] = new Array(n + 1).fill(0); + f[0] = 1; + for (const a of s) { + for (let j = n; j; --j) { + const b = t[j - 1]; + if (a === b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; +} +``` + ### **Rust** ```rust @@ -163,30 +297,6 @@ impl Solution { } ``` -### **TypeScript** - -```ts -function numDistinct(s: string, t: string): number { - const m = s.length; - const n = t.length; - const dp: number[][] = new Array(m + 1) - .fill(0) - .map(() => new Array(n + 1).fill(0)); - for (let i = 0; i <= m; ++i) { - dp[i][0] = 1; - } - for (let i = 1; i <= m; ++i) { - for (let j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; - if (s.charAt(i - 1) === t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; - } - } - } - return dp[m][n]; -} -``` - ### **...** ``` diff --git a/solution/0100-0199/0115.Distinct Subsequences/Solution.cpp b/solution/0100-0199/0115.Distinct Subsequences/Solution.cpp index dbb6dfdbc982a..eff3166f6e6e6 100644 --- a/solution/0100-0199/0115.Distinct Subsequences/Solution.cpp +++ b/solution/0100-0199/0115.Distinct Subsequences/Solution.cpp @@ -1,19 +1,18 @@ -class Solution { -public: - int numDistinct(string s, string t) { - int m = s.size(), n = t.size(); - vector> dp(m + 1, vector(n + 1)); - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; - } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; - if (s[i - 1] == t[j - 1]) { - dp[i][j] += dp[i - 1][j - 1]; - } - } - } - return dp[m][n]; - } +class Solution { +public: + int numDistinct(string s, string t) { + int n = t.size(); + unsigned long long f[n + 1]; + memset(f, 0, sizeof(f)); + f[0] = 1; + for (char& a : s) { + for (int j = n; j; --j) { + char b = t[j - 1]; + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; + } }; \ No newline at end of file diff --git a/solution/0100-0199/0115.Distinct Subsequences/Solution.go b/solution/0100-0199/0115.Distinct Subsequences/Solution.go index 14555730d2ed9..3b1eed97f2db4 100644 --- a/solution/0100-0199/0115.Distinct Subsequences/Solution.go +++ b/solution/0100-0199/0115.Distinct Subsequences/Solution.go @@ -1,17 +1,13 @@ func numDistinct(s string, t string) int { - m, n := len(s), len(t) - dp := make([][]int, m+1) - for i := 0; i <= m; i++ { - dp[i] = make([]int, n+1) - dp[i][0] = 1 - } - for i := 1; i <= m; i++ { - for j := 1; j <= n; j++ { - dp[i][j] = dp[i-1][j] - if s[i-1] == t[j-1] { - dp[i][j] += dp[i-1][j-1] + n := len(t) + f := make([]int, n+1) + f[0] = 1 + for _, a := range s { + for j := n; j > 0; j-- { + if b := t[j-1]; byte(a) == b { + f[j] += f[j-1] } } } - return dp[m][n] + return f[n] } \ No newline at end of file diff --git a/solution/0100-0199/0115.Distinct Subsequences/Solution.java b/solution/0100-0199/0115.Distinct Subsequences/Solution.java index fbc4cf5fe181e..0c90de4f2d637 100644 --- a/solution/0100-0199/0115.Distinct Subsequences/Solution.java +++ b/solution/0100-0199/0115.Distinct Subsequences/Solution.java @@ -1,18 +1,16 @@ -class Solution { - public int numDistinct(String s, String t) { - int m = s.length(), n = t.length(); - int[][] dp = new int[m + 1][n + 1]; - for (int i = 0; i <= m; ++i) { - dp[i][0] = 1; - } - for (int i = 1; i <= m; ++i) { - for (int j = 1; j <= n; ++j) { - dp[i][j] += dp[i - 1][j]; - if (s.charAt(i - 1) == t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; - } - } - } - return dp[m][n]; - } +class Solution { + public int numDistinct(String s, String t) { + int n = t.length(); + int[] f = new int[n + 1]; + f[0] = 1; + for (char a : s.toCharArray()) { + for (int j = n; j > 0; --j) { + char b = t.charAt(j - 1); + if (a == b) { + f[j] += f[j - 1]; + } + } + } + return f[n]; + } } \ No newline at end of file diff --git a/solution/0100-0199/0115.Distinct Subsequences/Solution.py b/solution/0100-0199/0115.Distinct Subsequences/Solution.py index e463bef16fdc4..9e7e02af1363e 100644 --- a/solution/0100-0199/0115.Distinct Subsequences/Solution.py +++ b/solution/0100-0199/0115.Distinct Subsequences/Solution.py @@ -1,12 +1,9 @@ -class Solution: - def numDistinct(self, s: str, t: str) -> int: - m, n = len(s), len(t) - dp = [[0] * (n + 1) for _ in range(m + 1)] - for i in range(m + 1): - dp[i][0] = 1 - for i in range(1, m + 1): - for j in range(1, n + 1): - dp[i][j] = dp[i - 1][j] - if s[i - 1] == t[j - 1]: - dp[i][j] += dp[i - 1][j - 1] - return dp[m][n] +class Solution: + def numDistinct(self, s: str, t: str) -> int: + n = len(t) + f = [1] + [0] * n + for a in s: + for j in range(n, 0, -1): + if a == t[j - 1]: + f[j] += f[j - 1] + return f[n] diff --git a/solution/0100-0199/0115.Distinct Subsequences/Solution.ts b/solution/0100-0199/0115.Distinct Subsequences/Solution.ts index ce23d6d36a220..f254f30e9f3f8 100644 --- a/solution/0100-0199/0115.Distinct Subsequences/Solution.ts +++ b/solution/0100-0199/0115.Distinct Subsequences/Solution.ts @@ -1,19 +1,14 @@ function numDistinct(s: string, t: string): number { - const m = s.length; const n = t.length; - const dp: number[][] = new Array(m + 1) - .fill(0) - .map(() => new Array(n + 1).fill(0)); - for (let i = 0; i <= m; ++i) { - dp[i][0] = 1; - } - for (let i = 1; i <= m; ++i) { - for (let j = 1; j <= n; ++j) { - dp[i][j] = dp[i - 1][j]; - if (s.charAt(i - 1) === t.charAt(j - 1)) { - dp[i][j] += dp[i - 1][j - 1]; + const f: number[] = new Array(n + 1).fill(0); + f[0] = 1; + for (const a of s) { + for (let j = n; j; --j) { + const b = t[j - 1]; + if (a === b) { + f[j] += f[j - 1]; } } } - return dp[m][n]; + return f[n]; }