动态规划子序列问题05:不相交的线

191 阅读3分钟

不相交的线

力扣1035. 不相交的线 - 力扣(LeetCode)
在两条独立的水平线上按给定的顺序写下 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 的直线相交。
示例 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

相信不少朋友看到这道题⽬都没啥思路,我们来逐步分析⼀下。
绘制⼀些连接两个数字 A[i] 和 B[j] 的直线,只要 A[i] == B[j],且直线不能相交!
直线不能相交,这就是说明在字符串A中 找到⼀个与字符串B相同的⼦序列,且这个⼦序列不能改变相对顺序,只要相对顺序不改变,链接相同数字的直线就不会相交。
拿示例⼀A = [1,4,2], B = [1,2,4]为例,相交情况如图:

image.png
其实也就是说A和B的最⻓公共⼦序列是[1,4],⻓度为2。 这个公共⼦序列指的是相对顺序不变(即数字4在字符串A中数字1的后⾯,那么数字4也应该在字符串B数字1的后⾯)
这么分析完之后,⼤家可以发现:本题说是求绘制的最⼤连线数,其实就是求两个字符串的最⻓公共⼦序列的⻓度!
那么本题就和我们刚刚讲过的这道题⽬动态规划:最⻓公共⼦序列就是⼀样⼀样的了。 ⼀样到什么程度呢? 把字符串名字改⼀下,其他代码都不⽤改,直接copy过来就⾏了。其实本题就是求最⻓公共⼦序列的⻓度,介于我们上一篇文章讲过动态规划:最⻓公共⼦序列,所以本题我就不再做动规五部曲分析了。
如果⼤家有点遗忘了最⻓公共⼦序列,就再看⼀下这篇:动态规划子序列问题04:最长公共子序列 - 掘金 (juejin.cn) Java代码如下:

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int l = nums1.length;
        int L = nums2.length;
        int[][] dp = new int[l + 1][L + 1];
        for(int i = 1; i <= l; i++)
            for(int j = 1; j <= L; j++)
                if(nums1[i - 1] == nums2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);

        return dp[l][L];
    }
}