不相交的线
在两条独立的水平线上按给定的顺序写下nums1和nums2中的整数。
现在,可以绘制一些连接两个数字nums1[i]和nums2[j]的直线,这些直线需要同时满足满足:
nums1[i]==nums2[j] 且绘制的直线不与任何其他连线(非水平线)相交。 请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。
以这种方法绘制线条,并返回可以绘制的最大连线数。
思路
- 首先分析题目:当nums1[i]==nums2[j],两个数字才可以连线,且该直线不能和其他连线相交,也就说要保持序列的相对顺序。
- 求最大连线数,也就是求最长子序列长度。
- 解决最长子序列长度问题,最常见的方法是动态规划。
- nums1的长度为m,nums2的长度为n,定义m+1行n+1列的dp二维数组,其中dp[i][j]表示nums1[0:i-1]和nums2[0:j-1]的最长子序列长度。
- 当nums1[i]==nums2[j]时,dp[i+1][j+1]=dp[i][j]+1
- 当nums1[i]!=nums2[j]时,可以考虑下面两个场景:nums1[0:i+1]和nums2[0:j] 和nums1[0:i]和nums2[0;j+1]。因此dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1])
- 综上所述,可以得到状态方程。
示例1
输入:nums1 = [1,4,2], nums2 = [1,2,4]
输出:2
解释:可以画出两条不交叉的线,如上图所示。
但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。
示例2
输入:nums1 = [2,5,1,2,5], nums2 = [10,5,2,1,5,2]
输出:3
解法
func maxUncrossedLines(nums1 []int, nums2 []int) int {
dp:=make([][]int,len(nums1)+1)
for i:=0;i<len(dp);i++{ // 定义dp二维数组,len(nums1)*len(nums2)
dp[i]=make([]int,len(nums2)+1)
}
for i:=0;i<len(nums1);i++{
for j:=0;j<len(nums2);j++{
if nums1[i]==nums2[j]{ // 两元素相等,则nums1[0:i-1]和nums2[0:j-1]的最长子序列长度加1即可。
dp[i+1][j+1]=dp[i][j]+1
}else{
dp[i+1][j+1]=getMaxValue2(dp[i][j+1],dp[i+1][j]) // 上述两类情况的最大值
}
}
return dp[len(nums1)][len(nums2)]
}
func getMaxValue2(a,b int)int{
if a>b{
return a
}
return b
}