Skip to content

Commit dcdf695

Browse files
authored
feat: add solutions to lc problem: No.1035 (#3399)
No.1035.Uncrossed Lines
1 parent ac07a33 commit dcdf695

File tree

8 files changed

+184
-105
lines changed

8 files changed

+184
-105
lines changed

solution/1000-1099/1035.Uncrossed Lines/README.md

+63-41
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ tags:
3939
<pre>
4040
<strong>输入:</strong>nums1 = <span id="example-input-1-1">[1,4,2]</span>, nums2 = <span id="example-input-1-2">[1,2,4]</span>
4141
<strong>输出:</strong><span id="example-output-1">2</span>
42-
<strong>解释:</strong>可以画出两条不交叉的线,如上图所示。
42+
<strong>解释:</strong>可以画出两条不交叉的线,如上图所示。
4343
但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。
4444
</pre>
4545

@@ -79,19 +79,15 @@ tags:
7979

8080
### 方法一:动态规划
8181

82-
最长公共子序列问题
82+
我们定义 $f[i][j]$ 表示 $\textit{nums1}$ 前 $i$ 个数和 $\textit{nums2}$ 前 $j$ 个数的最大连线数。初始时 $f[i][j] = 0$,答案即为 $f[m][n]$
8383

84-
定义 $dp[i][j]$ 表示数组 `nums1` 的前 $i$ 个元素和数组 `nums2` 的前 $j$ 个元素的最长公共子序列的长度。则有:
84+
当 $\textit{nums1}[i-1] = \textit{nums2}[j-1]$ 时,我们可以在 $\textit{nums1}$ 的前 $i-1$ 个数和 $\textit{nums2}$ 的前 $j-1$ 个数的基础上增加一条连线,此时 $f[i][j] = f[i-1][j-1] + 1$。
8585

86-
$$
87-
dp[i][j]=
88-
\begin{cases}
89-
dp[i-1][j-1]+1, & nums1[i-1]=nums2[j-1] \\
90-
\max(dp[i-1][j], dp[i][j-1]), & nums1[i-1]\neq nums2[j-1]
91-
\end{cases}
92-
$$
86+
当 $\textit{nums1}[i-1] \neq \textit{nums2}[j-1]$ 时,我们要么在 $\textit{nums1}$ 的前 $i-1$ 个数和 $\textit{nums2}$ 的前 $j$ 个数的基础上求解,要么在 $\textit{nums1}$ 的前 $i$ 个数和 $\textit{nums2}$ 的前 $j-1$ 个数的基础上求解,取两者的最大值,即 $f[i][j] = \max(f[i-1][j], f[i][j-1])$。
9387

94-
时间复杂度 $O(m\times n)$,空间复杂度 $O(m\times n)$。其中 $m$, $n$ 分别为数组 `nums1``nums2` 的长度。
88+
最后返回 $f[m][n]$ 即可。
89+
90+
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度。
9591

9692
<!-- tabs:start -->
9793

@@ -101,34 +97,33 @@ $$
10197
class Solution:
10298
def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
10399
m, n = len(nums1), len(nums2)
104-
dp = [[0] * (n + 1) for i in range(m + 1)]
105-
for i in range(1, m + 1):
106-
for j in range(1, n + 1):
107-
if nums1[i - 1] == nums2[j - 1]:
108-
dp[i][j] = dp[i - 1][j - 1] + 1
100+
f = [[0] * (n + 1) for _ in range(m + 1)]
101+
for i, x in enumerate(nums1, 1):
102+
for j, y in enumerate(nums2, 1):
103+
if x == y:
104+
f[i][j] = f[i - 1][j - 1] + 1
109105
else:
110-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
111-
return dp[m][n]
106+
f[i][j] = max(f[i - 1][j], f[i][j - 1])
107+
return f[m][n]
112108
```
113109

114110
#### Java
115111

116112
```java
117113
class Solution {
118114
public int maxUncrossedLines(int[] nums1, int[] nums2) {
119-
int m = nums1.length;
120-
int n = nums2.length;
121-
int[][] dp = new int[m + 1][n + 1];
122-
for (int i = 1; i <= m; i++) {
123-
for (int j = 1; j <= n; j++) {
115+
int m = nums1.length, n = nums2.length;
116+
int[][] f = new int[m + 1][n + 1];
117+
for (int i = 1; i <= m; ++i) {
118+
for (int j = 1; j <= n; ++j) {
124119
if (nums1[i - 1] == nums2[j - 1]) {
125-
dp[i][j] = dp[i - 1][j - 1] + 1;
120+
f[i][j] = f[i - 1][j - 1] + 1;
126121
} else {
127-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
122+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
128123
}
129124
}
130125
}
131-
return dp[m][n];
126+
return f[m][n];
132127
}
133128
}
134129
```
@@ -140,17 +135,18 @@ class Solution {
140135
public:
141136
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
142137
int m = nums1.size(), n = nums2.size();
143-
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
138+
int f[m + 1][n + 1];
139+
memset(f, 0, sizeof(f));
144140
for (int i = 1; i <= m; ++i) {
145141
for (int j = 1; j <= n; ++j) {
146142
if (nums1[i - 1] == nums2[j - 1]) {
147-
dp[i][j] = dp[i - 1][j - 1] + 1;
143+
f[i][j] = f[i - 1][j - 1] + 1;
148144
} else {
149-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
145+
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
150146
}
151147
}
152148
}
153-
return dp[m][n];
149+
return f[m][n];
154150
}
155151
};
156152
```
@@ -160,20 +156,20 @@ public:
160156
```go
161157
func maxUncrossedLines(nums1 []int, nums2 []int) int {
162158
m, n := len(nums1), len(nums2)
163-
dp := make([][]int, m+1)
164-
for i := range dp {
165-
dp[i] = make([]int, n+1)
159+
f := make([][]int, m+1)
160+
for i := range f {
161+
f[i] = make([]int, n+1)
166162
}
167163
for i := 1; i <= m; i++ {
168164
for j := 1; j <= n; j++ {
169165
if nums1[i-1] == nums2[j-1] {
170-
dp[i][j] = dp[i-1][j-1] + 1
166+
f[i][j] = f[i-1][j-1] + 1
171167
} else {
172-
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
168+
f[i][j] = max(f[i-1][j], f[i][j-1])
173169
}
174170
}
175171
}
176-
return dp[m][n]
172+
return f[m][n]
177173
}
178174
```
179175

@@ -183,19 +179,45 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int {
183179
function maxUncrossedLines(nums1: number[], nums2: number[]): number {
184180
const m = nums1.length;
185181
const n = nums2.length;
186-
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
182+
const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
187183
for (let i = 1; i <= m; ++i) {
188184
for (let j = 1; j <= n; ++j) {
189-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
190-
if (nums1[i - 1] == nums2[j - 1]) {
191-
dp[i][j] = dp[i - 1][j - 1] + 1;
185+
if (nums1[i - 1] === nums2[j - 1]) {
186+
f[i][j] = f[i - 1][j - 1] + 1;
187+
} else {
188+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
192189
}
193190
}
194191
}
195-
return dp[m][n];
192+
return f[m][n];
196193
}
197194
```
198195

196+
#### JavaScript
197+
198+
```js
199+
/**
200+
* @param {number[]} nums1
201+
* @param {number[]} nums2
202+
* @return {number}
203+
*/
204+
var maxUncrossedLines = function (nums1, nums2) {
205+
const m = nums1.length;
206+
const n = nums2.length;
207+
const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
208+
for (let i = 1; i <= m; ++i) {
209+
for (let j = 1; j <= n; ++j) {
210+
if (nums1[i - 1] === nums2[j - 1]) {
211+
f[i][j] = f[i - 1][j - 1] + 1;
212+
} else {
213+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
214+
}
215+
}
216+
}
217+
return f[m][n];
218+
};
219+
```
220+
199221
<!-- tabs:end -->
200222

201223
<!-- solution:end -->

solution/1000-1099/1035.Uncrossed Lines/README_EN.md

+67-31
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,17 @@ We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2]
7070

7171
<!-- solution:start -->
7272

73-
### Solution 1
73+
### Solution 1: Dynamic Programming
74+
75+
We define $f[i][j]$ to represent the maximum number of connections between the first $i$ numbers of $\textit{nums1}$ and the first $j$ numbers of $\textit{nums2}$. Initially, $f[i][j] = 0$, and the answer is $f[m][n]$.
76+
77+
When $\textit{nums1}[i-1] = \textit{nums2}[j-1]$, we can add a connection based on the first $i-1$ numbers of $\textit{nums1}$ and the first $j-1$ numbers of $\textit{nums2}$. In this case, $f[i][j] = f[i-1][j-1] + 1$.
78+
79+
When $\textit{nums1}[i-1] \neq \textit{nums2}[j-1]$, we either solve based on the first $i-1$ numbers of $\textit{nums1}$ and the first $j$ numbers of $\textit{nums2}$, or solve based on the first $i$ numbers of $\textit{nums1}$ and the first $j-1$ numbers of $\textit{nums2}$, taking the maximum of the two. That is, $f[i][j] = \max(f[i-1][j], f[i][j-1])$.
80+
81+
Finally, return $f[m][n]$.
82+
83+
The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the lengths of $\textit{nums1}$ and $\textit{nums2}$, respectively.
7484

7585
<!-- tabs:start -->
7686

@@ -80,34 +90,33 @@ We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2]
8090
class Solution:
8191
def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
8292
m, n = len(nums1), len(nums2)
83-
dp = [[0] * (n + 1) for i in range(m + 1)]
84-
for i in range(1, m + 1):
85-
for j in range(1, n + 1):
86-
if nums1[i - 1] == nums2[j - 1]:
87-
dp[i][j] = dp[i - 1][j - 1] + 1
93+
f = [[0] * (n + 1) for _ in range(m + 1)]
94+
for i, x in enumerate(nums1, 1):
95+
for j, y in enumerate(nums2, 1):
96+
if x == y:
97+
f[i][j] = f[i - 1][j - 1] + 1
8898
else:
89-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
90-
return dp[m][n]
99+
f[i][j] = max(f[i - 1][j], f[i][j - 1])
100+
return f[m][n]
91101
```
92102

93103
#### Java
94104

95105
```java
96106
class Solution {
97107
public int maxUncrossedLines(int[] nums1, int[] nums2) {
98-
int m = nums1.length;
99-
int n = nums2.length;
100-
int[][] dp = new int[m + 1][n + 1];
101-
for (int i = 1; i <= m; i++) {
102-
for (int j = 1; j <= n; j++) {
108+
int m = nums1.length, n = nums2.length;
109+
int[][] f = new int[m + 1][n + 1];
110+
for (int i = 1; i <= m; ++i) {
111+
for (int j = 1; j <= n; ++j) {
103112
if (nums1[i - 1] == nums2[j - 1]) {
104-
dp[i][j] = dp[i - 1][j - 1] + 1;
113+
f[i][j] = f[i - 1][j - 1] + 1;
105114
} else {
106-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
115+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
107116
}
108117
}
109118
}
110-
return dp[m][n];
119+
return f[m][n];
111120
}
112121
}
113122
```
@@ -119,17 +128,18 @@ class Solution {
119128
public:
120129
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
121130
int m = nums1.size(), n = nums2.size();
122-
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
131+
int f[m + 1][n + 1];
132+
memset(f, 0, sizeof(f));
123133
for (int i = 1; i <= m; ++i) {
124134
for (int j = 1; j <= n; ++j) {
125135
if (nums1[i - 1] == nums2[j - 1]) {
126-
dp[i][j] = dp[i - 1][j - 1] + 1;
136+
f[i][j] = f[i - 1][j - 1] + 1;
127137
} else {
128-
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
138+
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
129139
}
130140
}
131141
}
132-
return dp[m][n];
142+
return f[m][n];
133143
}
134144
};
135145
```
@@ -139,20 +149,20 @@ public:
139149
```go
140150
func maxUncrossedLines(nums1 []int, nums2 []int) int {
141151
m, n := len(nums1), len(nums2)
142-
dp := make([][]int, m+1)
143-
for i := range dp {
144-
dp[i] = make([]int, n+1)
152+
f := make([][]int, m+1)
153+
for i := range f {
154+
f[i] = make([]int, n+1)
145155
}
146156
for i := 1; i <= m; i++ {
147157
for j := 1; j <= n; j++ {
148158
if nums1[i-1] == nums2[j-1] {
149-
dp[i][j] = dp[i-1][j-1] + 1
159+
f[i][j] = f[i-1][j-1] + 1
150160
} else {
151-
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
161+
f[i][j] = max(f[i-1][j], f[i][j-1])
152162
}
153163
}
154164
}
155-
return dp[m][n]
165+
return f[m][n]
156166
}
157167
```
158168

@@ -162,19 +172,45 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int {
162172
function maxUncrossedLines(nums1: number[], nums2: number[]): number {
163173
const m = nums1.length;
164174
const n = nums2.length;
165-
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
175+
const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
166176
for (let i = 1; i <= m; ++i) {
167177
for (let j = 1; j <= n; ++j) {
168-
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
169-
if (nums1[i - 1] == nums2[j - 1]) {
170-
dp[i][j] = dp[i - 1][j - 1] + 1;
178+
if (nums1[i - 1] === nums2[j - 1]) {
179+
f[i][j] = f[i - 1][j - 1] + 1;
180+
} else {
181+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
171182
}
172183
}
173184
}
174-
return dp[m][n];
185+
return f[m][n];
175186
}
176187
```
177188

189+
#### JavaScript
190+
191+
```js
192+
/**
193+
* @param {number[]} nums1
194+
* @param {number[]} nums2
195+
* @return {number}
196+
*/
197+
var maxUncrossedLines = function (nums1, nums2) {
198+
const m = nums1.length;
199+
const n = nums2.length;
200+
const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
201+
for (let i = 1; i <= m; ++i) {
202+
for (let j = 1; j <= n; ++j) {
203+
if (nums1[i - 1] === nums2[j - 1]) {
204+
f[i][j] = f[i - 1][j - 1] + 1;
205+
} else {
206+
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
207+
}
208+
}
209+
}
210+
return f[m][n];
211+
};
212+
```
213+
178214
<!-- tabs:end -->
179215

180216
<!-- solution:end -->

solution/1000-1099/1035.Uncrossed Lines/Solution.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ class Solution {
22
public:
33
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
44
int m = nums1.size(), n = nums2.size();
5-
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
5+
int f[m + 1][n + 1];
6+
memset(f, 0, sizeof(f));
67
for (int i = 1; i <= m; ++i) {
78
for (int j = 1; j <= n; ++j) {
89
if (nums1[i - 1] == nums2[j - 1]) {
9-
dp[i][j] = dp[i - 1][j - 1] + 1;
10+
f[i][j] = f[i - 1][j - 1] + 1;
1011
} else {
11-
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]);
1213
}
1314
}
1415
}
15-
return dp[m][n];
16+
return f[m][n];
1617
}
17-
};
18+
};

0 commit comments

Comments
 (0)