bet9链接用学过的DP模型解Uncrossed Lines_Leetcode

由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之间。

观察

连线的规则是:

  1. 两个阵列要遇到相同的数字,可以建立一条新连线。
  2. 新的连线不能和别的连线交叉

目标:
最多的连线数目

想要连线数目越多越好,
代表两个阵列的相同的数字越多越好,而且不能和别的连线交叉。


演算法化简到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 )。

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值