59
59
60
60
** 方法一:动态规划**
61
61
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$ 的长度 。
63
63
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 ] )$。即状态转移方程为 :
65
65
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
+ $$
67
73
68
- 时间复杂度 O(mn) 。
74
+ 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为 $text1$ 和 $text2$ 的长度 。
69
75
70
76
<!-- tabs:start -->
71
77
77
83
class Solution :
78
84
def longestCommonSubsequence (self , text1 : str , text2 : str ) -> int :
79
85
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 )]
81
87
for i in range (1 , m + 1 ):
82
88
for j in range (1 , n + 1 ):
83
89
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
85
91
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 ]
88
94
```
89
95
90
96
### ** Java**
@@ -95,17 +101,17 @@ class Solution:
95
101
class Solution {
96
102
public int longestCommonSubsequence (String text1 , String text2 ) {
97
103
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 ];
99
105
for (int i = 1 ; i <= m; ++ i) {
100
106
for (int j = 1 ; j <= n; ++ j) {
101
107
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 ;
103
109
} 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 ]);
105
111
}
106
112
}
107
113
}
108
- return dp [m][n];
114
+ return f [m][n];
109
115
}
110
116
}
111
117
```
@@ -117,17 +123,17 @@ class Solution {
117
123
public:
118
124
int longestCommonSubsequence(string text1, string text2) {
119
125
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));
121
127
for (int i = 1; i <= m; ++i) {
122
128
for (int j = 1; j <= n; ++j) {
123
129
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;
125
131
} 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 ] );
127
133
}
128
134
}
129
135
}
130
- return dp [ m] [ n ] ;
136
+ return f [ m] [ n ] ;
131
137
}
132
138
};
133
139
```
@@ -137,20 +143,20 @@ public:
137
143
```go
138
144
func longestCommonSubsequence(text1 string, text2 string) int {
139
145
m, n := len(text1), len(text2)
140
- dp := make([][]int, m+1)
146
+ f := make([][]int, m+1)
141
147
for i := 0; i <= m; i++ {
142
- dp [i] = make([]int, n+1)
148
+ f [i] = make([]int, n+1)
143
149
}
144
150
for i := 1; i <= m; i++ {
145
151
for j := 1; j <= n; j++ {
146
152
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
148
154
} 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])
150
156
}
151
157
}
152
158
}
153
- return dp [m][n]
159
+ return f [m][n]
154
160
}
155
161
156
162
func max(a, b int) int {
@@ -172,20 +178,42 @@ func max(a, b int) int {
172
178
var longestCommonSubsequence = function (text1 , text2 ) {
173
179
const m = text1 .length ;
174
180
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 ));
176
182
for (let i = 1 ; i <= m; ++ i) {
177
183
for (let j = 1 ; j <= n; ++ j) {
178
184
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 ;
180
186
} 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 ]);
182
188
}
183
189
}
184
190
}
185
- return dp [m][n];
191
+ return f [m][n];
186
192
};
187
193
```
188
194
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
+
189
217
### ** ...**
190
218
191
219
```
0 commit comments