leetcode
leetcode 951 ~ 1000
不相交的线

不相交的线

难度:

标签:

题目描述

在两条独立的水平线上按给定的顺序写下 nums1nums2 中的整数。

现在,可以绘制一些连接两个数字 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

 

提示:

  • 1 <= nums1.length, nums2.length <= 500
  • 1 <= nums1[i], nums2[j] <= 2000

 

代码结果

运行时间: 35 ms, 内存: 16.2 MB


解释

方法:

本题解的思路是将问题转化为寻找两个数组之间的最长递增子序列(Longest Increasing Subsequence, LIS)的问题。首先,为了方便处理,确保nums1是两个数组中较短的一个。然后,使用一个字典dic来存储nums1中每个数字的所有出现位置,并按照逆序存储,以便后续操作。接下来,遍历nums2数组,将nums2中的元素按照在nums1中出现的位置顺序记录到一个列表tmp中。这一步是为了找到所有在nums1和nums2中都出现的元素,并保留其在nums1中的位置。最后,通过计算tmp列表的最长递增子序列的长度来确定最大的不相交的线的数量,这是因为这些位置的递增序列对应于不相交的连接线。

时间复杂度:

O(m log m)

空间复杂度:

O(n + m)

代码细节讲解

🦆
为什么在解决问题时首先选择将nums1和nums2中较短的数组作为nums1?这种选择对算法的效率有何影响?
在该算法实现中,选择较短的数组作为nums1主要是为了优化空间复杂度和提高算法效率。具体来说,由于需要建立一个字典来存储nums1中每个元素的出现位置,如果nums1较短,则字典的大小也会较小,从而减少内存使用。此外,遍历nums2并查找其元素在nums1的位置时,较短的nums1意味着在字典中查找操作的平均复杂度较低,从而可以加快整个算法的执行速度。
🦆
在构建字典dic时,为什么选择逆序存储nums1中元素的出现位置?这样做有什么特别的优势吗?
逆序存储nums1中元素的出现位置的主要优势在于便于处理重复元素并保持他们的相对顺序。当nums2中的元素在nums1中多次出现时,逆序存储可以确保我们总是能够尽可能地使用最靠后的元素,从而在构造tmp数组时保持最长递增子序列的潜在长度。这样做有助于确保找到的递增子序列是有效的,不会因为重复利用前面的元素而导致错误。
🦆
如何理解算法中对tmp列表使用二分查找来计算最长递增子序列(LIS)的过程?
算法中利用二分查找来构建最长递增子序列是通过维护一个动态的列表dp,该列表存储当前找到的最长递增子序列的元素。对于tmp中的每个元素x,使用二分查找确定它在dp中的位置i。如果x可以添加到dp的末尾(即i等于dp的长度),则直接添加x;如果i小于dp的长度,则替换dp中的第i个元素为x。这种方法有效地保持了dp的长度为当前的最长递增子序列的长度,并确保dp始终尽可能小,从而提高查找和更新的效率。
🦆
给定的算法实现中,是否考虑了nums1或nums2为空的情况,如果没有,应该如何处理?
在给定的算法实现中没有显式处理nums1或nums2为空的情况。如果任一数组为空,则最长递增子序列的长度自然应为0,因为没有可用的元素来形成连线。为了处理这种情况,应在算法开始时添加一个检查,如果发现任一数组为空,则直接返回0。这样可以有效避免后续的无意义计算,并保证算法的鲁棒性。

相关问题

编辑距离

给你两个单词 word1 和 word2请返回将 word1 转换成 word2 所使用的最少操作数  。

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

 

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

 

提示:

  • 0 <= word1.length, word2.length <= 500
  • word1word2 由小写英文字母组成