题目描述
We write the integers of A and B (in the order they are given) on two separate horizontal lines.
Now, we may draw connecting lines: a straight line connecting two numbers A[i] and B[j] such that:
A[i] == B[j];
The line we draw does not intersect any other connecting (non-horizontal) line.
Note that a connecting lines cannot intersect even at the endpoints: each number can only belong to one connecting line.
Return the maximum number of connecting lines we can draw in this way.
例子
Example 1:
Input: A = [1,4,2], B = [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 A[1]=4 to B[2]=4 will intersect the line from A[2]=2 to B[1]=2.
Example 2:
Input: A = [2,5,1,2,5], B = [10,5,2,1,5,2]
Output: 3
Example 3:
Input: A = [1,3,7,1,7,5], B = [1,9,2,5,1]
Output: 2
解释
给A和B两个一维数组,里面的每个数字表示线段的一个端点。我们每次可以把A和B中数组相同的两个点连接起来。问最多可以连多少条不相交的线段。注意,一个端点只能用一次,否则也视为相交。
思路 动态规划
我们用一个dp的二维数组去存我们所需要的最大的不相交的线段数。dp(i, j)表示在A[:i]和B[:j]的最大不相交线段数。
那么怎么求状态转移方程呢?在i, j这个点,如果恰好A[i] = B[j],则我们直接把dp[i - 1][j - 1]的值再加上1即可。这是因为 dp[i - 1][j - 1]表示的线段的端点均为i,j之前的点因此将i, j连线必不会和之前的线段相交。而如果A[i] != B[j],则dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]),这是因为我们无法将这两个点连线,又需要保留之前的数值为下一个i, j键值对做判断,所以当然就把之前可能的最大值拿过来就好。
代码
class Solution(object):
def maxUncrossedLines(self, A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: int
"""
m, n = len(A), len(B)
A1, B1 = [0] + A, [0] + B
dp = [[0] * (n + 1) for i in range(m + 1)]
for i in range(1, m + 1):
for j in range(1,n + 1):
if A1[i] == B1[j]:
dp[i][j] = 1 + dp[i - 1][j - 1]
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
return dp[-1][-1]