由bet9链接 вт989点сс ku链接编译题目。
叙述Uncrossed Lines
给定两个输入整数阵列,若在两个阵列遇到相同的数字可以连成一线,但是有规定连线不可和别的连线有交叉。
请问最多可以形成几条连线?
测试范例
示例 1:
输入:nums1 = [ 1 , 4 , 2 ] , nums2 = [ 1 , 2 , 4 ]输出:2解释:我们可以像图中这样
画2 条不相交的线。但我们不能画3 条不相交的线,因为从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
示例 3:
输入:nums1 = [ 1 , 3 , 7 , 1 , 7 , 5 ] ,nums2 = [ 1 , 9 , 2 , 5 , 1 ]输出:2
约束条件
限制:
1 <= nums1.length, nums2.length <= 500
输入阵列的长度都介于1~500之间。
1 <= nums1[i], nums2[j] <= 2000
阵列里的每个数字都介于1~2000之间。
观察
连线的规则是:
- 两个阵列要遇到相同的数字,可以建立一条新连线。
- 新的连线不能和别的连线交叉。
目标:
最多的连线数目。
想要连线数目越多越好,
代表两个阵列的相同的数字越多越好,而且不能和别的连线交叉。
演算法化简到LCS最长共同子序列的DP模型
1. 定义DP状态
DP[i,j]代表阵列nums1[0~i], nums2[0~j]的最多连线数目。
最终所求是什么?
自然就是两个阵列的最多连线数目= DP[ len(nums1)-1, len(nums2)-1]
2. 推导DP状态转移关系式
如果nums1[i] == nums2[j]
代表现在数字相同,可以多建立一条连线,
总连线数= 剩余的子阵列连线数目+ 1
DP[i, j] = DP[i-1, j-1] + 1
如果nums1[i] != nums2[j]
代表现在数字不同,无法多建立新连线,
总连线数= 去掉当下的数字,剩余的子阵列连线数目
DP[i,j] = Max{ DP[i-1,j],DP[i,j-1] }
3.厘清DP初始状态
最小规模的题目是什么?
其实就是对比到空阵列的时候
这时候,肯定没有相同的数字,连线数目=0
如果 i == -1,则 DP[i, j] = 0
如果 j == -1,则 DP[i, j] = 0
程式码化简到LCS最长共同子序列的DP模型
class Solution :def maxUncrossedLines (self ,A :List [ int ] ,B :List [ int ] )- >
int :# key:索引对# value:连接的最大计数 dp_table = { } def connect (idx_a ,
idx_b ):if (idx_a ,idx_b )在dp_table中:return dp_table [ (idx_a ,idx_b )] if idx_a
== - 1 or idx_b == - 1 :#与空列表相比,任何列表都不会给出未交叉的线 dp_table
[ (idx_a ,idx_b )] = 0 return 0 elif A [ idx_a ] == B [ idx_b ] :
dp_table [ (idx_a ,idx_b )] = connect (idx_a -1 ,idx_b - 1 )+ 1返回dp_table [
(idx_a ,idx_b )] else :dp_table [ (idx_a ,idx_b )] = max (connect (idx_a - 1 ,
idx_b ),connect (idx_a ,idx_b - 1 ))返回dp_table [ (idx_a ,idx_b
)] # --------------------------------------------返回connect (len (A )- 1 ,len (B
)-1 )
等价的Bottom up DP程式码
class Solution :def maxUncrossedLines ( self ,A :List [ int ] ,B :List [ int ] ) - >
int : #填充一个虚拟值 -1 表示空列表 A = [ -1 ] + A B = [ -1 ] + B h
,w = len (A ),len (B ) dp_table = [ [ 0 for _ in range (w )] for _ in range
(h )] for y in range (1 ,h ):for x in range (1 ,w ):if A [ y ] == B [ x ] :#当前数
字匹配,再添加一条未交叉的线 dp_table [ y ] [ x ] = dp_table [ y - 1 ] [ x
- 1 ] + 1 else :#当前数字不匹配,回溯以找到最大未交叉的线 dp_table [ y ] [
x ] = max ( dp_table [ y ] [ x - 1 ] , dp_table [ y - 1 ] [ x ] )返回dp_table [ - 1 ] [ - 1
]
复杂度分析
时间复杂度: O( m * n )
考虑到索引移动配对,总共有O(m*n)个状态,
每个状态可以在O(1)内计算完成。
空间复杂度: O( m*n )
DP table 所需空间为O( m*n )。