力扣第1035题 不相交的线中等 c++ (最长公共子序列) 动态规划 附Java代码

题目

1035. 不相交的线

中等

相关标签

数组 动态规划

在两条独立的水平线上按给定的顺序写下 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

思路和解题方法

  • vector<vector<int>> dp(A.size() + 1, vector<int>(B.size() + 1, 0));:创建一个二维数组dp,用于记录A和B中不相交线的最大数量。其中,第一维表示A数组的长度加1,第二维表示B数组的长度加1,初始值为0。
  • for (int i = 1; i <= A.size(); i++):从第二个数字开始遍历A数组,因为需要与前一个数字比较。
  • for (int j = 1; j <= B.size(); j++):从第二个数字开始遍历B数组,因为需要与前一个数字比较。
  • if (A[i - 1] == B[j - 1]):如果当前数字相等,表示可以连接一条不相交线,在不相交线的基础上再加1,更新不相交线的数量。此处的i-1j-1是因为dp数组从下标1开始计算,而A和B数组从下标0开始计算。
  • dp[i][j] = dp[i - 1][j - 1] + 1;:如果当前数字相等,更新不相交线的数量。
  • else:如果当前数字不相等。
  • dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);:取前一行或前一列的最大值作为不相交线的数量。
  • return dp[A.size()][B.size()];:返回不相交线的最大数量。

复杂度

时间复杂度:

O(mn)

时间复杂度是O(mn),其中m和n分别是数组A和B的长度。因为要遍历A和B中的所有数字,并对每个数字进行比较和操作。

空间复杂度

O(mn)

空间复杂度也是O(mn),因为需要创建一个二维数组dp来记录不相交线的最大数量。其中,第一维是A数组的长度加1,第二维是B数组的长度加1。

c++ 代码

cpp 复制代码
class Solution {
public:
    int maxUncrossedLines(vector<int>& A, vector<int>& B) {
        // 创建一个二维数组dp,用于记录A和B中不相交线的最大数量
        vector<vector<int>> dp(A.size() + 1, vector<int>(B.size() + 1, 0));
        
        for (int i = 1; i <= A.size(); i++) { // 遍历A数组
            for (int j = 1; j <= B.size(); j++) { // 遍历B数组
                if (A[i - 1] == B[j - 1]) { // 如果当前数字相等,表示可以连接一条不相交线
                    dp[i][j] = dp[i - 1][j - 1] + 1; // 更新不相交线的数量
                }
                else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); // 如果当前数字不相等,取前一行或前一列的最大值作为不相交线的数量
                }
            }
        }
        
        return dp[A.size()][B.size()]; // 返回不相交线的最大数量
    }
};

Java代码

  • 创建一个大小为(len1+1)*(len2+1)的二维数组dp,用于存储最大不相交线段数量,默认初值为0。
  • 遍历数组nums1和nums2,从第一个元素到最后一个元素。在循环中,根据当前元素的相等与否来更新dp[i][j]的值。如果nums1中第i个元素等于nums2中第j个元素,则可以将这个元素作为一条不相交的线段,更新dp[i][j]的值为dp[i-1][j-1] + 1。如果nums1中第i个元素不等于nums2中第j个元素,则最大不相交线段数量取决于dp[i-1][j]和dp[i][j-1]的较大值。
  • 最后,返回dp[len1][len2],即最大不相交线段数量。
java 复制代码
class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int len1 = nums1.length; // 数组nums1的长度
        int len2 = nums2.length; // 数组nums2的长度
        int[][] dp = new int[len1 + 1][len2 + 1]; // 创建一个大小为(len1+1)*(len2+1)的二维数组dp,用于存储最大不相交线段数量,默认初值为0

        for (int i = 1; i <= len1; i++) { // 遍历数组nums1,从第一个元素到最后一个元素
            for (int j = 1; j <= len2; j++) { // 遍历数组nums2,从第一个元素到最后一个元素
                if (nums1[i - 1] == nums2[j - 1]) { // 如果nums1中第i个元素等于nums2中第j个元素,则可以将这个元素作为一条不相交的线段
                    dp[i][j] = dp[i - 1][j - 1] + 1; // 更新dp[i][j]的值,dp[i][j]表示以nums1的前i个元素和nums2的前j个元素结尾的最大不相交线段数量
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); // 如果nums1中第i个元素不等于nums2中第j个元素,则最大不相交线段数量取决于dp[i-1][j]和dp[i][j-1]的较大值
                }
            }
        }

        return dp[len1][len2]; // 返回最大不相交线段数量
    }
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦 >人< 。

相关推荐
装不满的克莱因瓶4 分钟前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
scan7247 分钟前
LILAC采样算法
人工智能·算法·机器学习
n北斗12 分钟前
常用类晨考day15
java
骇客野人15 分钟前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
菌菌的快乐生活28 分钟前
理解支持向量机
算法·机器学习·支持向量机
大山同学32 分钟前
第三章线性判别函数(二)
线性代数·算法·机器学习
axxy20001 小时前
leetcode之hot100---240搜索二维矩阵II(C++)
数据结构·算法
黑客Ash1 小时前
安全算法基础(一)
算法·安全
yuanbenshidiaos1 小时前
c++---------数据类型
java·jvm·c++
向宇it1 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎