1035. Uncrossed Lines¶
Edited by Charles
Medium · Python · Dynamic Programming
Problem
Read the original problem on LeetCode.
The official page contains the problem statement, examples, and constraints.
Explanation, examples & other approaches
Core idea
Given two integer arrays nums1 and nums2, return the maximum number of connecting lines that can be drawn between equal numbers such that no two lines intersect.
Although the problem is described in terms of drawing lines, it is essentially asking for the Longest Common Subsequence (LCS) of the two arrays.
Original study notes follow, including intermediate snippets and earlier attempts.
Idea¶
Given two integer arrays nums1 and nums2, return the maximum number of connecting lines that can be drawn between equal numbers such that no two lines intersect.
Although the problem is described in terms of drawing lines, it is essentially asking for the Longest Common Subsequence (LCS) of the two arrays.
The reason is that once two matching elements are connected, their relative order must be preserved to avoid crossing lines, which is exactly the definition of a subsequence.
For example:
The maximum number of uncrossed lines is:
One possible matching is:
Dynamic Programming¶
State Definition¶
Let
denote:
The maximum number of uncrossed lines that can be drawn between
nums1[:i]andnums2[:j].
Equivalently,
The length of the Longest Common Subsequence (LCS) between
nums1[:i]andnums2[:j].
Initialization¶
If either array is empty, no lines can be drawn.
Therefore, initialize the first row and first column to 0.
The extra row and column eliminate boundary checks.
State Transition¶
Case 1: Current elements match¶
If
the two elements can be connected without crossing previous lines.
Update:
Case 2: Current elements do not match¶
If the current elements are different, one of them cannot participate in the optimal solution.
There are two possibilities:
- Ignore the current element in
nums1 - Ignore the current element in
nums2
Take the better result:
Transition equation:
if nums1[i - 1] == nums2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
The key idea is:
Connecting two equal numbers is equivalent to selecting one character in the Longest Common Subsequence problem.
Final Answer¶
Since dp[i][j] represents the maximum number of uncrossed lines between the prefixes of the two arrays, the final answer is
which is equivalent to
Example¶
Initialization:
Match 1¶
Update:
Compare 4 and 2¶
Update:
Match 4¶
Update:
Compare 2 and 4¶
Update:
Final answer:
Complexity Analysis¶
Time Complexity
where
m = len(nums1)n = len(nums2)
Each state is computed exactly once.
Space Complexity
A 2D DP table is required.
Note: The DP table can be optimized to O(n) using a rolling array because each state only depends on the previous row and the current row.
Summary¶
State Definition
or equivalently,
Initialization
State Transition
if nums1[i - 1] == nums2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
Traversal Order
Traverse both arrays from left to right while filling the DP table.
Final Answer
Common Mistakes¶
- Although the problem describes drawing lines, it is exactly the Longest Common Subsequence (LCS) problem.
- Since the lines cannot cross, the matched elements must preserve their relative order.
- When the current elements do not match, do not reset the state to
0.
Instead,
because previous matches are still valid.
dp[i][j]represents the optimal solution for the prefixes of the two arrays, not the solution ending at the current elements.- The answer is directly stored in
There is no need to maintain a separate global maximum.
Study record
| Field | Value |
|---|---|
| Attempts | 1 |
| Mastery | ❚ |
Python solution¶
class Solution:
def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
l1 = len(nums1)
l2 = len(nums2)
dp = [[0] * (l2 + 1) for _ in range(l1 + 1)]
for i in range(1, l1 + 1):
for j in range(1, l2 + 1):
if nums1[i - 1] == nums2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
return dp[-1][-1]