赞
踩
在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线需要同时满足满足: nums1[i] == nums2[j]. 且绘制的直线不与任何其他连线(非水平线)相交。
请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。以这种方法绘制线条,并返回可以绘制的最大连线数。
示例 1:
输入:nums1 = [1,4,2], nums2 = [1,2,4]
输出:2
解释:可以画出两条不交叉的线,如下图所示。
但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。
问题花里胡哨说了一堆,究其本质,其实是求解数组 nums1和 nums2的最长公共子序列的长度。
给定两个数组 nums1和 nums2,当
n
u
m
s
1
[
i
]
=
=
n
u
m
s
2
[
j
]
\ nums1\left [ i\right ] == nums2\left [ j\right ]
nums1[i]==nums2[j]时,可以用一条直线连接 nums1[i]和nums2[j]。假设一共绘制了 k 条互不相交的直线,其中第 x 条直线连接
n
u
m
s
1
[
i
x
]
\ nums1\left [ i_x \right ]
nums1[ix]和
n
u
m
s
2
[
j
x
]
\ nums2\left [ j_x \right ]
nums2[jx],则对于任意
1
<
x
<
k
\ 1< x < k
1<x<k都有
n
u
m
s
1
[
i
x
]
=
=
n
u
m
s
2
[
j
x
]
\ nums1\left [ i_x \right ] == nums2\left [ j_x \right ]
nums1[ix]==nums2[jx],其中
i
1
<
i
2
<
i
k
\ i_{1} < i_{2} <i_{k}
i1<i2<ik,
j
1
<
j
2
<
j
k
\ j_{1} < j_{2} < j_{k}
j1<j2<jk。上述 k 条互不相交的直线分别连接了数组 nums1 和 nums 2的 k 对相等的元素,而且这 k 对相等的元素在两个数组中的相对顺序是一致的,因此,这 k 对相等的元素组成的序列即为数组 nums1 和 nums2的公共子序列。
求解公共子序列是典型的二维动态规划问题。
假设数组 nums1和 nums2 的长度分别为 m 和 n,创建 m+1 行 n+1 列的二维数组 dp,其中
d
p
[
i
]
[
j
]
\ dp\left [ i \right ]\left [ j \right ]
dp[i][j]表示
n
u
m
s
1
[
0
:
1
]
\ nums1\left [ 0:1 \right ]
nums1[0:1]和
n
u
m
s
2
[
0
:
j
]
\ nums2\left [ 0:j \right ]
nums2[0:j]的最长公共子序列的长度。
n
u
m
s
1
[
0
:
1
]
\ nums1\left [ 0:1 \right ]
nums1[0:1]表示数组 nums1 的长度为 i 的前缀;
n
u
m
s
2
[
0
:
j
]
\ nums2\left [ 0:j \right ]
nums2[0:j]表示数组 nums2 的长度为 j 的前缀。
代码:
class Solution { public: int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) { int m = nums1.size(), n = nums2.size(); vector<vector<int>> dp(m + 1, vector<int>(n + 1)); for (int i = 1; i <= m; i++) { int num1 = nums1[i - 1]; for (int j = 1; j <= n; j++) { int num2 = nums2[j - 1]; if (num1 == num2) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[m][n]; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。