代码随想录算法训练营第五十三天|1143.最长公共子序列、1035.不相交的线、53.最大子序和

本文介绍了三种编程问题的解决方案:使用动态规划解决1143.最长公共子序列,通过相同元素计数确定1035.不相交线段的绘制数量,以及53.最大子序和问题中的贪心策略。每种问题都涉及到了数组操作和递推关系的计算。
摘要由CSDN通过智能技术生成

代码随想录算法训练营第五十三天|1143.最长公共子序列、1035.不相交的线、53.最大子序和

1143.最长公共子序列

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3 。

题解:在上一题的基础上多考虑一个条件,那就是当前两个数组元素还要分开考虑一下。

  • dp(i,j) :表示数组1 到以 i-1 为结尾 和 数组2 以 j-1 为结尾的最长公共子序列

  • 递推公式 :如果两个元素相等,那就是最长重复子数组的情况 dp(i,j)=max(dp(i-1,j-1)+1,dp(i,j))

    ​ 如果当前它们不相等,那要考虑1的前一位和2的当前位,以及2的前一位和1的当前位是否相等。 dp(i,j)=max(dp(i-1,j),dp(i,j-1))

  • 初始化:把边界初始化为0

  • 遍历顺序:从小到大

  • 打印dp数组

代码

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        //模糊掉边界的处理
        int len1=text1.length()+1;
        int len2=text2.length()+1;
        int [][] dp=new int[len1][len2];
        int res=0;
        for(int i=1;i<len1;i++){
            for(int j=1;j<len2;j++){
                if(text1.charAt(i-1)==text2.charAt(j-1))
                    dp[i][j]=Math.max(dp[i][j],dp[i-1][j-1]+1);
                else 
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                res=Math.max(res,dp[i][j]);
            }
        }
        return res;
    }
}

1035.不相交的线

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

现在,可以绘制一些连接两个数字 nums1[i]nums2[j] 的直线,这些直线需要同时满足:

  • nums1[i] == nums2[j]
  • 且绘制的直线不与任何其他连线(非水平线)相交。

请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。

以这种方法绘制线条,并返回可以绘制的最大连线数。

示例 1:

img

输入:nums1 = [1,4,2], nums2 = [1,2,4]
输出:2
解释:可以画出两条不交叉的线,如上图所示。 
但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。

题解:这个题和上一个题是一样的,只是描述不一样。

代码

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int len1=nums1.length+1;
        int len2=nums2.length+1;
        int res=0;
        int [][] dp=new int[len1][len2];
        for(int i=1;i<len1;i++){
            for(int j=1;j<len2;j++){
                if(nums1[i-1]==nums2[j-1])
                    dp[i][j]=Math.max(dp[i][j],dp[i-1][j-1]+1);
                else 
                    dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                res=Math.max(res,dp[i][j]);
            }
        }
        return res;
    }
}

53.最大子序和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组

是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

题解:这个题贪心写过,贪心的思想是只要相加的和是正数,那么就加上这个值,不是的话就sum=0,重新开始即可。

dp思想:

  • dp[i]: 以 i 为结尾的连续子序列的最大和
  • 递推公式: dp[i]=max(dp[i-1]+nums[i],nums[i]);
  • 初始化: dp[0]=nums[0];
  • 遍历顺序:从小到大
  • 打印dp数组

代码

class Solution {
    public int maxSubArray(int[] nums) {
        int len=nums.length;
        int [] dp=new int [len];
        int res=nums[0];
        dp[0]=nums[0];
        for(int i=1;i<len;i++){
            dp[i]=Math.max(dp[i-1]+nums[i],nums[i]);
            res=Math.max(res,dp[i]);
        }
      return res;
    }
}

贪心算法:

class Solution {
    public int maxSubArray(int[] nums) {
        int len=nums.length;
        int res=Integer.MIN_VALUE;
        int sum=0;
        for(int i=0;i<len;i++){
            sum+=nums[i];
            if(sum>res) res=sum;
            if(sum<0) sum=0;
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值