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

题目

1035. 不相交的线

中等

相关标签

数组 动态规划

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

提示:

  • 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-1和j-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,从第一个元素到最后一个元素。在循环中,根据当前元素的相等与否来更新dpij的值。如果nums1中第i个元素等于nums2中第j个元素,则可以将这个元素作为一条不相交的线段,更新dpij的值为dpi-1j-1 + 1。如果nums1中第i个元素不等于nums2中第j个元素,则最大不相交线段数量取决于dpi-1j和dpij-1的较大值。
  • 最后,返回dplen1len2,即最大不相交线段数量。
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]; // 返回最大不相交线段数量
    }
}

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

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

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

相关推荐
_Evan_Yao10 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd11 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼11 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
BK贝壳11 小时前
bool-hybrid-array 落盘我只认 .bha:用 Create_BHA / Ask_BHA 做布尔数组序列化
数据结构·python·numpy·1024程序员节
会编程的小孩11 小时前
C++ qt的安装
c++
thefool11226612 小时前
TCP 1
java·1024程序员节
企业数字化笔记14 小时前
视频人体姿态怎么做三维可视化?2D关键点、深度局限与技术选型
人工智能·算法·音视频
金銀銅鐵14 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
?abc!14 小时前
(数组)581. 最短无序连续子数组
数据结构·算法·leetcode
AI人工智能+电脑小能手14 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务