题目如下:
在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。
现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线需要同时满足满足:
nums1[i] == nums2[j]
且绘制的直线不与任何其他连线(非水平线)相交。
请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。
以这种方法绘制线条,并返回可以绘制的最大连线数。
仔细读题,会发现一个特别神奇的东西,这道题其实就是最长公共子序列问题换了一种问法,其实换汤不换药,看到这里是不是觉得恍然大悟,如梦初醒呢?
最长公共子序列问题是一道非常经典的动态规划问题,如果最长公共子序列搞懂了,那这道题就不会有任何问题,如果还没搞懂,建议先看看最长公共子序列问题。
代码如下:
class Solution {
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int dp[][] = new int[nums2.length][nums1.length];
// 首先dp数组的第一行第一列
// 填充第一列
for( int i = 0; i < dp.length; ++i ){
if( nums2[i] == nums1[0] ){
dp[i][0] = 1;
++i;
while( i < dp.length ){
dp[i++][0] = 1;
}
}
}
// 填充第一行
for( int i = 0; i < dp[0].length; ++i ){
if( nums1[i] == nums2[0] ){
dp[0][i] = 1;
++i;
while( i < dp[0].length ){
dp[0][i++] = 1;
}
}
}
// 填充剩下的
for( int i = 1; i < dp.length; ++i ){
for( int j = 1; j < dp[0].length; ++j ){
int temp = dp[i - 1][j - 1];
if( nums1[j] == nums2[i] ){
dp[i][j] = ++temp;
}else{
dp[i][j] = Math.max(dp[i][j - 1],dp[i - 1][j]);
}
}
}
return dp[dp.length - 1][dp[0].length - 1];
}
}