( 动态规划) 1035. 不相交的线 ——【Leetcode每日一题】

这篇具有很好参考价值的文章主要介绍了( 动态规划) 1035. 不相交的线 ——【Leetcode每日一题】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

❓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

💡思路:动态规划

由于连线不能相交,则可以只看nums2的第 i 个数字 和 nums1的第 j 个数字:

  1. 如果相等,则可以直接相连:此时nums2的前 i 个数字 和 nums1的前 j 个数字的连线数等于nums2的前 i - 1 个数字 和 nums1的前 j - 1 个数字的连线数 + 1

  2. 如果不相等,则不能连接:可以取nums2的前 i - 1 个数字 和 nums1的前 j 个数字的连线数,或nums2的前 i 个数字 和 nums1的前 j - 1 个数字的连线数 ,取两者最大值

根据上述分析我们定义二维dp数组dp[i][j]表示数组nums2的前 i 个数字 和 nums1的前 j 个数字可以绘制的最大连线数, 举例如下:

( 动态规划) 1035. 不相交的线 ——【Leetcode每日一题】

  • 如果nums2[i]等于nums1[j]nums2[i]可以与nums1[j]相连,也可以不连,则状态转移公式为:
    d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 dp[i][j] = dp[i-1][j-1] + 1 dp[i][j]=dp[i1][j1]+1
  • 如果nums2[i]不等于nums1[j],则状态转移公式为:
    d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) dp[i][j] = max(dp[i-1][j], dp[i][j-1]) dp[i][j]=max(dp[i1][j],dp[i][j1])

⭐️ 空间优化

由于dp[i][j] 只与上一行和当前行有关系,所以可以进行空间优化,只需要两个一维数组 dp[2][j]即可,一个保存当前行,另一个保存当前行的上一行,状态转移公式为:

  • nums2[i]等于nums1[j]
    d p [ s e c ] [ j ] = d p [ f i r ] [ j − 1 ] + 1 dp[sec][j] = dp[fir][j-1] + 1 dp[sec][j]=dp[fir][j1]+1
  • nums2[i]不等于nums1[j],:
    d p [ s e c ] [ j ] = m a x ( d p [ f i r ] [ j ] , d p [ s e c ] [ j − 1 ] ) dp[sec][j] = max(dp[fir][j], dp[sec][j-1]) dp[sec][j]=max(dp[fir][j],dp[sec][j1])

行号 firsec交替变换。

🍁代码:(Java、C++)

Java

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int n = nums2.length;
        int m = nums1.length;
        int[][] dp = new int[n + 1][m + 1];
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(nums1[j - 1] == nums2[i - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                else{
                    dp[i][j] = dp[i][j - 1] > dp[i - 1][j] ? dp[i][j - 1] : dp[i - 1][j];
                }
            }
        }
        return dp[n][m];
    }
}

C++

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        int n = nums2.size();
        int m = nums1.size();
        vector<vector<int>>dp(n + 1, vector<int>(m + 1));
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(nums1[j - 1] == nums2[i - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                else{
                    dp[i][j] = dp[i][j - 1] > dp[i - 1][j] ? dp[i][j - 1] : dp[i - 1][j];
                }
            }
        }
        return dp[n][m];
    }
};

⭐️空间优化

Java

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int n = nums2.length;
        int m = nums1.length;
        int[][] dp = new int[2][m + 1];
        int fir = 0, sec = 1;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(nums1[j - 1] == nums2[i - 1]){
                    dp[sec][j] = dp[fir][j - 1] + 1;
                }
                else{
                    dp[sec][j] = dp[sec][j - 1] > dp[fir][j] ? dp[sec][j - 1] : dp[fir][j];
                }
            }
            int tmp = fir;
            fir = sec;
            sec = tmp;
        }
        return Math.max(dp[0][m], dp[1][m]);
    }
}

C++

class Solution {
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
        int n = nums2.size();
        int m = nums1.size();
        vector<vector<int>>dp (2, vector<int>(m + 1));
        int fir = 0, sec = 1;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(nums1[j - 1] == nums2[i - 1]){
                    dp[sec][j] = dp[fir][j - 1] + 1;
                }
                else{
                    dp[sec][j] = dp[sec][j - 1] > dp[fir][j] ? dp[sec][j - 1] : dp[fir][j];
                }
            }
            int tmp = fir;
            fir = sec;
            sec = tmp;
        }
        return max(dp[0][m], dp[1][m]);
    }
};
🚀 运行结果:

( 动态规划) 1035. 不相交的线 ——【Leetcode每日一题】

🕔 复杂度分析:
  • 时间复杂度 O ( m ∗ n ) O(m*n) O(mn),其中 m 为数组nums1的长度,n 为数组nums2的长度。
  • 空间复杂度 O ( m ) O(m) O(m),空间优化只需 2 * m的空间,优化前的空间复杂度为 O ( m ∗ n ) O(m*n) O(mn)

题目来源:力扣。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我LeetCode主页 / CSDN—力扣专栏,每日更新!文章来源地址https://www.toymoban.com/news/detail-451508.html

注: 如有不足,欢迎指正!

到了这里,关于( 动态规划) 1035. 不相交的线 ——【Leetcode每日一题】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 代码随想录第53天|● 1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和 动态规划

    dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j] 通过pre记录前一个dp[j-1] 循环中记录cur为dp[i],循环结束后再更新pre=cur。 和最长公共子序列相同 注意pre和cur放置的位置 dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i

    2024年03月08日
    浏览(51)
  • leetcode 1035. 不相交的线

             本题可以转化为:求两数组的最长公共子序列。 进而可以用dp算法解决。 方法类似于这题最长公共子序列 。 代码如下:

    2024年02月11日
    浏览(35)
  • LeetCode刷题 | 1143. 最长公共子序列、1035. 不相交的线、53. 最大子数组和

    给定两个字符串  text1  和  text2 ,返回这两个字符串的最长  公共子序列  的长度。如果不存在  公共子序列  ,返回  0  。 一个字符串的  子序列   是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后

    2024年02月12日
    浏览(44)
  • 【Leetcode每日一题】 动态规划 - 地下城游戏(难度⭐⭐⭐)(61)

    1. 题目解析 题目链接:174. 地下城游戏 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 一、状态表定义 在解决地下城游戏问题时,我们首先需要对状态进行恰当的定义。一个直观的想法是,从起点开始,到达[i, j]位置时所需的最低初始

    2024年04月29日
    浏览(44)
  • ( 动态规划) 516. 最长回文子序列 ——【Leetcode每日一题】

    难度:中等 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 示例 1: 输入:s = “bbbab” 输出:4 解释:一个可能的最长回文子序列为 “bbbb” 。 示例

    2024年02月06日
    浏览(44)
  • (动态规划) 132. 分割回文串 II ——【Leetcode每日一题】

    难度:困难 给你一个字符串 s ,请你将 s 分割成一些子串,使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1: 输入:s = “aab” 输出:1 解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。 示例 2: 输入:s = “a” 输出:0 示例 3: 输入:

    2024年02月15日
    浏览(46)
  • 代码随想Day53 | 1143.最长公共子序列、1035.不相交的线、53. 最大子序和

    本题和 718. 最长重复子数组 的区别就是本题不要求连续,所以在两个字符不相等的时候,逻辑不相同,当不相同的时候,需要找到dp[i-1][j]和dp[i][j-1]之间的最大值,因为不相等的时候需要找出退而求上一个状态的两个值的最大,这样才能得到最长公共子序列数,其他的思路

    2024年02月03日
    浏览(50)
  • (动态规划) 剑指 Offer 60. n个骰子的点数 ——【Leetcode每日一题】

    难度:中等 把 n 个骰子扔在地上,所有骰子朝上一面的点数之和为 s 。输入 n ,打印出s的所有可能的值出现的概率。 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。 示例 1: 输入: 1 输出: [0.16667,0.16667,0.16667,

    2024年02月11日
    浏览(45)
  • ( 动态规划) 674. 最长连续递增序列 / 718. 最长重复子数组——【Leetcode每日一题】

    难度:简单 给定一个未经排序的整数数组,找到最长且 连续递增的子序列 ,并返回该序列的长度。 连续递增的子序列 可以由两个下标 l 和 r(l r) 确定,如果对于每个 l = i r ,都有 nums[i] nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。

    2024年02月05日
    浏览(52)
  • (动态规划) 剑指 Offer 42. 连续子数组的最大和 ——【Leetcode每日一题】

    难度:简单 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。 要求时间复杂度为 O(n) 。 示例1: 输入: nums = [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 提示 : 1 = a r r . l e n g t h = 1 0 5 1 = arr.length = 10^

    2024年02月11日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包