
Problem Statement
In this task, you are provided with two integer arrays, nums1
and nums2
. The arrays are visualized as two separate horizontal lines where each integer in the arrays is depicted in the given order. The objective is to draw the maximum number of 'connecting lines' between the numbers on these two lines based on the following criteria:
- A connecting line can only be drawn between
nums1[i]
andnums2[j]
ifnums1[i] == nums2[j]
. - These connecting lines must not intersect or overlap with one another; even at their endpoints, which means each number can participate in only one connecting line.
The challenge is to calculate the maximum number of such non-intersecting connecting lines that can be drawn between the two arrays.
Examples
Example 1
Input:
nums1 = [1,4,2], nums2 = [1,2,4]
Output:
2
Explanation:
We can draw 2 uncrossed lines as in the diagram. We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2] = 4 will intersect the line from nums1[2]=2 to nums2[1]=2.
Example 2
Input:
nums1 = [2,5,1,2,5], nums2 = [10,5,2,1,5,2]
Output:
3
Example 3
Input:
nums1 = [1,3,7,1,7,5], nums2 = [1,9,2,5,1]
Output:
2
Constraints
1 <= nums1.length, nums2.length <= 500
1 <= nums1[i], nums2[j] <= 2000
Approach and Intuition
The task is fundamentally a problem of finding a maximum matching in a bipartite graph where each number in the arrays represents a node, and an edge can be drawn between nodes if their corresponding numbers are equal and do not lead to any crossed edges.
We can solve this using the concept from the Longest Common Subsequence (LCS) problem:
The objective of drawing maximum non-intersecting lines between
nums1
andnums2
where corresponding values are equal is similar to finding LCS, where the order matters and no two selected pairs can be in conflict. Each line can be thought of as a pairing(i, j)
such thatnums1[i] == nums2[j]
.We will use a dynamic programming table
dp
wheredp[i][j]
represents the maximum number of non-intersecting lines between the subarraysnums1[0...i-1]
andnums2[0...j-1]
.- If
nums1[i-1] == nums2[j-1]
, then adding these two to our solution might provide a better solution if this forms a part of a common subsequence. Thus, we might considerdp[i-1][j-1] + 1
fordp[i][j]
. - Otherwise, we should consider the best achievable without using either
nums1[i-1]
ornums2[j-1]
, which would be the max from either excluding the current element ofnums1
ornums2
, sodp[i][j] = max(dp[i-1][j], dp[i][j-1])
.
- If
Begin with a base case where if either array is empty (
i == 0
orj == 0
), no lines can be drawn.Fill up the dp table iteratively, and the value in
dp[length of nums1][length of nums2]
will give the maximum number of such lines.
The solution thus obtained will ensure that the lines are drawn such that no two lines intersect, effectively solving the problem using dynamic programming based on the principles of finding the longest common subsequence.
Solutions
- C++
- Java
class Solution {
public:
int maxNonCrossingLines(vector<int>& A, vector<int>& B) {
int sizeA = A.size(), sizeB = B.size();
vector<int> curr(sizeB + 1), last(sizeB + 1);
for (int i = 1; i <= sizeA; i++) {
for (int j = 1; j <= sizeB; j++) {
if (A[i - 1] == B[j - 1]) {
curr[j] = 1 + last[j - 1];
} else {
curr[j] = max(curr[j - 1], last[j]);
}
}
last = curr;
}
return curr[sizeB];
}
};
The provided C++ solution aims to solve the problem of finding the maximum number of non-crossing lines that can be drawn between the elements of two integer arrays. This problem essentially maps to finding the longest common subsequence (LCS) between the two arrays.
Here's a breakdown of the code's approach:
- A solution class
Solution
is defined containing the functionmaxNonCrossingLines
. - The function receives two integer vectors,
A
andB
. sizeA
andsizeB
store the sizes of vectorsA
andB
respectively.- Two integer vectors,
curr
andlast
, each of sizesizeB + 1
, are used to store the current and the previous lengths of LCS up to each index. - The outer loop runs through each element in vector
A
, and the inner loop runs through each element in vectorB
. - During the traversal, if the elements
A[i - 1]
andB[j - 1]
match:curr[j]
is set to1 + last[j - 1]
, updating it to the length of LCS found so far including the current match.
- If there is no match:
curr[j]
is set to the maximum of the left (curr[j - 1]
) and the upper values (last[j]
) to ensure the longest sequence length is carried forward.
- After each inner loop iteration,
last
is updated to the current values ofcurr
to preserve the context for the next iteration. - Finally, the function returns
curr[sizeB]
which contains the length of the longest non-crossing lines (LCS) after considering all elements.
This algorithm efficiently computes the maximum number of non-crossing lines with a time complexity of O(n*m), where n and m are the sizes of vectors A
and B
, respectively, using a dynamic programming approach that uses two rolling arrays to keep the space complexity linear relative to the size of vector B
.
class Solution {
public int maximumUncrossedLines(int[] A, int[] B) {
int lenA = A.length;
int lenB = B.length;
int[] current = new int[lenB + 1];
int[] previous = new int[lenB + 1];
for (int i = 1; i <= lenA; i++) {
for (int j = 1; j <= lenB; j++) {
if (A[i - 1] == B[j - 1]) {
current[j] = 1 + previous[j - 1];
} else {
current[j] = Math.max(current[j - 1], previous[j]);
}
}
previous = current.clone();
}
return current[lenB];
}
}
The provided Java solution effectively tackles the problem of finding maximum number of uncrossed lines between two arrays, which can be visualized as a variant of the Longest Common Subsequence problem. Here’s a concise summary of how this code works:
- Initialize two integer arrays,
current
andprevious
, sized one more than the length of array B (lenB + 1
), to store intermediate results for dynamic programming. - Employ a nested loop where the outer loop iterates through each element of array A, and the inner loop iterates through each element of array B.
- Inside the inner loop, check if the current elements of A and B,
A[i-1]
andB[j-1]
, are equal:- If they are, set
current[j]
to1 + previous[j - 1]
to build on the matched sequence. - If not, set
current[j]
to the maximum ofcurrent[j-1]
orprevious[j]
to carry forward the maximum uncrossed lines count without extending the sequence.
- If they are, set
- After completing each inner loop iteration, copy the
current
array to theprevious
array withcurrent.clone()
to update the states for the next iteration. - The final result, after looping through both arrays, will be stored in
current[lenB]
, which represents the maximum number of uncrossed lines between the two arrays.
This code utilizes dynamic programming efficiently by using only two arrays and updating them iteratively, minimizing space complexity while ensuring the optimal solution is computed.
No comments yet.