Skip to content

Commit 8f92875

Browse files
authored
feat: add solutions to lcof2 problem: No.095 (#1101)
1 parent 24d7654 commit 8f92875

File tree

11 files changed

+171
-76
lines changed

11 files changed

+171
-76
lines changed

lcof2/剑指 Offer II 095. 最长公共子序列/README.md

+53-25
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,19 @@
5959

6060
**方法一:动态规划**
6161

62-
定义 `dp[i][j]` 表示 `text1[0:i-1]``text2[0:j-1]` 的最长公共子序列(闭区间)
62+
我们定义 $f[i][j]$ 表示 $text1$ 的前 $i$ 个字符和 $text2$ 的前 $j$ 个字符的最长公共子序列的长度。那么答案为 $f[m][n]$,其中 $m$ 和 $n$ 分别为 $text1$ 和 $text2$ 的长度
6363

64-
递推公式如下
64+
如果 $text1$ 的第 $i$ 个字符和 $text2$ 的第 $j$ 个字符相同,则 $f[i][j] = f[i - 1][j - 1] + 1$;如果 $text1$ 的第 $i$ 个字符和 $text2$ 的第 $j$ 个字符不同,则 $f[i][j] = max(f[i - 1][j], f[i][j - 1])$。即状态转移方程为
6565

66-
![](https://fastly.jsdelivr.net/gh/doocs/leetcode@main/lcof2/剑指%20Offer%20II%20095.%20最长公共子序列/images/gif.gif)
66+
$$
67+
f[i][j] =
68+
\begin{cases}
69+
f[i - 1][j - 1] + 1, & text1[i - 1] = text2[j - 1] \\
70+
\max(f[i - 1][j], f[i][j - 1]), & text1[i - 1] \neq text2[j - 1]
71+
\end{cases}
72+
$$
6773

68-
时间复杂度 O(mn)
74+
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为 $text1$ 和 $text2$ 的长度
6975

7076
<!-- tabs:start -->
7177

@@ -77,14 +83,14 @@
7783
class Solution:
7884
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
7985
m, n = len(text1), len(text2)
80-
dp = [[0] * (n + 1) for _ in range(m + 1)]
86+
f = [[0] * (n + 1) for _ in range(m + 1)]
8187
for i in range(1, m + 1):
8288
for j in range(1, n + 1):
8389
if text1[i - 1] == text2[j - 1]:
84-
dp[i][j] = dp[i - 1][j - 1] + 1
90+
f[i][j] = f[i - 1][j - 1] + 1
8591
else:
86-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
87-
return dp[-1][-1]
92+
f[i][j] = max(f[i - 1][j], f[i][j - 1])
93+
return f[-1][-1]
8894
```
8995

9096
### **Java**
@@ -95,17 +101,17 @@ class Solution:
95101
class Solution {
96102
public int longestCommonSubsequence(String text1, String text2) {
97103
int m = text1.length(), n = text2.length();
98-
int[][] dp = new int[m + 1][n + 1];
104+
int[][] f = new int[m + 1][n + 1];
99105
for (int i = 1; i <= m; ++i) {
100106
for (int j = 1; j <= n; ++j) {
101107
if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
102-
dp[i][j] = dp[i - 1][j - 1] + 1;
108+
f[i][j] = f[i - 1][j - 1] + 1;
103109
} else {
104-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
110+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
105111
}
106112
}
107113
}
108-
return dp[m][n];
114+
return f[m][n];
109115
}
110116
}
111117
```
@@ -117,17 +123,17 @@ class Solution {
117123
public:
118124
int longestCommonSubsequence(string text1, string text2) {
119125
int m = text1.size(), n = text2.size();
120-
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
126+
vector<vector<int>> f(m + 1, vector<int>(n + 1));
121127
for (int i = 1; i <= m; ++i) {
122128
for (int j = 1; j <= n; ++j) {
123129
if (text1[i - 1] == text2[j - 1]) {
124-
dp[i][j] = dp[i - 1][j - 1] + 1;
130+
f[i][j] = f[i - 1][j - 1] + 1;
125131
} else {
126-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
132+
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
127133
}
128134
}
129135
}
130-
return dp[m][n];
136+
return f[m][n];
131137
}
132138
};
133139
```
@@ -137,20 +143,20 @@ public:
137143
```go
138144
func longestCommonSubsequence(text1 string, text2 string) int {
139145
m, n := len(text1), len(text2)
140-
dp := make([][]int, m+1)
146+
f := make([][]int, m+1)
141147
for i := 0; i <= m; i++ {
142-
dp[i] = make([]int, n+1)
148+
f[i] = make([]int, n+1)
143149
}
144150
for i := 1; i <= m; i++ {
145151
for j := 1; j <= n; j++ {
146152
if text1[i-1] == text2[j-1] {
147-
dp[i][j] = dp[i-1][j-1] + 1
153+
f[i][j] = f[i-1][j-1] + 1
148154
} else {
149-
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
155+
f[i][j] = max(f[i-1][j], f[i][j-1])
150156
}
151157
}
152158
}
153-
return dp[m][n]
159+
return f[m][n]
154160
}
155161
156162
func max(a, b int) int {
@@ -172,20 +178,42 @@ func max(a, b int) int {
172178
var longestCommonSubsequence = function (text1, text2) {
173179
const m = text1.length;
174180
const n = text2.length;
175-
const dp = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
181+
const f = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
176182
for (let i = 1; i <= m; ++i) {
177183
for (let j = 1; j <= n; ++j) {
178184
if (text1[i - 1] == text2[j - 1]) {
179-
dp[i][j] = dp[i - 1][j - 1] + 1;
185+
f[i][j] = f[i - 1][j - 1] + 1;
180186
} else {
181-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
187+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
182188
}
183189
}
184190
}
185-
return dp[m][n];
191+
return f[m][n];
186192
};
187193
```
188194

195+
### **TypeScript**
196+
197+
```ts
198+
function longestCommonSubsequence(text1: string, text2: string): number {
199+
const m = text1.length;
200+
const n = text2.length;
201+
const f: number[][] = new Array(m + 1)
202+
.fill(0)
203+
.map(() => new Array(n + 1).fill(0));
204+
for (let i = 1; i <= m; ++i) {
205+
for (let j = 1; j <= n; ++j) {
206+
if (text1[i - 1] == text2[j - 1]) {
207+
f[i][j] = f[i - 1][j - 1] + 1;
208+
} else {
209+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
210+
}
211+
}
212+
}
213+
return f[m][n];
214+
}
215+
```
216+
189217
### **...**
190218

191219
```
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
class Solution {
2-
public:
3-
int longestCommonSubsequence(string text1, string text2) {
4-
int m = text1.size(), n = text2.size();
5-
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
6-
for (int i = 1; i <= m; ++i) {
7-
for (int j = 1; j <= n; ++j) {
8-
if (text1[i - 1] == text2[j - 1]) {
9-
dp[i][j] = dp[i - 1][j - 1] + 1;
10-
} else {
11-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
12-
}
13-
}
14-
}
15-
return dp[m][n];
16-
}
1+
class Solution {
2+
public:
3+
int longestCommonSubsequence(string text1, string text2) {
4+
int m = text1.size(), n = text2.size();
5+
vector<vector<int>> f(m + 1, vector<int>(n + 1));
6+
for (int i = 1; i <= m; ++i) {
7+
for (int j = 1; j <= n; ++j) {
8+
if (text1[i - 1] == text2[j - 1]) {
9+
f[i][j] = f[i - 1][j - 1] + 1;
10+
} else {
11+
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
12+
}
13+
}
14+
}
15+
return f[m][n];
16+
}
1717
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
public class Solution {
2+
public int LongestCommonSubsequence(string text1, string text2) {
3+
int m = text1.Length, n = text2.Length;
4+
int[,] f = new int[m + 1, n + 1];
5+
for (int i = 1; i <= m; ++i) {
6+
for (int j = 1; j <= n; ++j) {
7+
if (text1[i - 1] == text2[j - 1]) {
8+
f[i, j] = f[i - 1, j - 1] + 1;
9+
} else {
10+
f[i, j] = Math.Max(f[i - 1, j], f[i, j - 1]);
11+
}
12+
}
13+
}
14+
return f[m, n];
15+
}
16+
}

lcof2/剑指 Offer II 095. 最长公共子序列/Solution.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
func longestCommonSubsequence(text1 string, text2 string) int {
22
m, n := len(text1), len(text2)
3-
dp := make([][]int, m+1)
3+
f := make([][]int, m+1)
44
for i := 0; i <= m; i++ {
5-
dp[i] = make([]int, n+1)
5+
f[i] = make([]int, n+1)
66
}
77
for i := 1; i <= m; i++ {
88
for j := 1; j <= n; j++ {
99
if text1[i-1] == text2[j-1] {
10-
dp[i][j] = dp[i-1][j-1] + 1
10+
f[i][j] = f[i-1][j-1] + 1
1111
} else {
12-
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
12+
f[i][j] = max(f[i-1][j], f[i][j-1])
1313
}
1414
}
1515
}
16-
return dp[m][n]
16+
return f[m][n]
1717
}
1818

1919
func max(a, b int) int {
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
class Solution {
2-
public int longestCommonSubsequence(String text1, String text2) {
3-
int m = text1.length(), n = text2.length();
4-
int[][] dp = new int[m + 1][n + 1];
5-
for (int i = 1; i <= m; ++i) {
6-
for (int j = 1; j <= n; ++j) {
7-
if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
8-
dp[i][j] = dp[i - 1][j - 1] + 1;
9-
} else {
10-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
11-
}
12-
}
13-
}
14-
return dp[m][n];
15-
}
1+
class Solution {
2+
public int longestCommonSubsequence(String text1, String text2) {
3+
int m = text1.length(), n = text2.length();
4+
int[][] f = new int[m + 1][n + 1];
5+
for (int i = 1; i <= m; ++i) {
6+
for (int j = 1; j <= n; ++j) {
7+
if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
8+
f[i][j] = f[i - 1][j - 1] + 1;
9+
} else {
10+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
11+
}
12+
}
13+
}
14+
return f[m][n];
15+
}
1616
}

lcof2/剑指 Offer II 095. 最长公共子序列/Solution.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
var longestCommonSubsequence = function (text1, text2) {
77
const m = text1.length;
88
const n = text2.length;
9-
const dp = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
9+
const f = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
1010
for (let i = 1; i <= m; ++i) {
1111
for (let j = 1; j <= n; ++j) {
1212
if (text1[i - 1] == text2[j - 1]) {
13-
dp[i][j] = dp[i - 1][j - 1] + 1;
13+
f[i][j] = f[i - 1][j - 1] + 1;
1414
} else {
15-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
15+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
1616
}
1717
}
1818
}
19-
return dp[m][n];
19+
return f[m][n];
2020
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution {
2+
fun longestCommonSubsequence(text1: String, text2: String): Int {
3+
val m = text1.length
4+
val n = text2.length
5+
val f = Array(m + 1) { IntArray(n + 1) }
6+
for (i in 1..m) {
7+
for (j in 1..n) {
8+
if (text1[i - 1] == text2[j - 1]) {
9+
f[i][j] = f[i - 1][j - 1] + 1
10+
} else {
11+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1])
12+
}
13+
}
14+
}
15+
return f[m][n]
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
class Solution:
2-
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
3-
m, n = len(text1), len(text2)
4-
dp = [[0] * (n + 1) for _ in range(m + 1)]
5-
for i in range(1, m + 1):
6-
for j in range(1, n + 1):
7-
if text1[i - 1] == text2[j - 1]:
8-
dp[i][j] = dp[i - 1][j - 1] + 1
9-
else:
10-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
11-
return dp[-1][-1]
1+
class Solution:
2+
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
3+
m, n = len(text1), len(text2)
4+
f = [[0] * (n + 1) for _ in range(m + 1)]
5+
for i in range(1, m + 1):
6+
for j in range(1, n + 1):
7+
if text1[i - 1] == text2[j - 1]:
8+
f[i][j] = f[i - 1][j - 1] + 1
9+
else:
10+
f[i][j] = max(f[i - 1][j], f[i][j - 1])
11+
return f[-1][-1]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
impl Solution {
2+
pub fn longest_common_subsequence(text1: String, text2: String) -> i32 {
3+
let (m, n) = (text1.len(), text2.len());
4+
let (text1, text2) = (text1.as_bytes(), text2.as_bytes());
5+
let mut f = vec![vec![0; n + 1]; m + 1];
6+
for i in 1..=m {
7+
for j in 1..=n {
8+
f[i][j] = if text1[i - 1] == text2[j - 1] {
9+
f[i - 1][j - 1] + 1
10+
} else {
11+
f[i - 1][j].max(f[i][j - 1])
12+
}
13+
}
14+
}
15+
f[m][n]
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function longestCommonSubsequence(text1: string, text2: string): number {
2+
const m = text1.length;
3+
const n = text2.length;
4+
const f: number[][] = new Array(m + 1)
5+
.fill(0)
6+
.map(() => new Array(n + 1).fill(0));
7+
for (let i = 1; i <= m; ++i) {
8+
for (let j = 1; j <= n; ++j) {
9+
if (text1[i - 1] == text2[j - 1]) {
10+
f[i][j] = f[i - 1][j - 1] + 1;
11+
} else {
12+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
13+
}
14+
}
15+
}
16+
return f[m][n];
17+
}
Binary file not shown.

0 commit comments

Comments
 (0)