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

文章介绍了如何使用动态规划方法解决最长公共子序列问题,通过定义二维数组dp来避免复杂初始化。同时,还提及了如何通过相似思路处理不相交线问题。最后提到了利用贪心法求解最大子序和的问题.
摘要由CSDN通过智能技术生成

1143.最长公共子序列

完成

思路:

定义二维dp数组,dp[i][j]代表以i-1结尾的text1和以j-1结尾的text2 的最长公共子序列长度,动态规划求子序列的相关问题中,dp数组这样定义是为了规避复杂的初始化,这是一个技巧。

代码

dp[i][j]代表以i结尾的text1和以j结尾的text2 的最长公共子序列长度

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        // dp[i][j]代表以i结尾的text1和以j结尾的text2 的最长公共子序列长度
        int[][] dp = new int[text1.length()][text2.length()];
        // 初始化开始--------------------------------------------------
        // 需要初始化最上行和最左列
        // 前面的元素为0,后一个元素需要比较得到;前面的元素为1,后一个元素一定是1
        dp[0][0] = text1.charAt(0) == text2.charAt(0)?1:0;
        int flag = dp[0][0];
        for (int i = 1; i < text1.length(); i++) { // 初始化最左列
            if(flag == 1){ // 前面的元素为1
                dp[i][0] = 1;
            }else{ // 前面的元素为0
                if(text2.charAt(0) == text1.charAt(i)){
                    dp[i][0] = 1;
                    flag = 1;
                }
            }
        }
        flag = dp[0][0];
        for (int j = 1; j < text2.length(); j++) {  // 初始化最上行
            if(flag == 1){
                dp[0][j] = 1;
            }else{
                if(text1.charAt(0) == text2.charAt(j)){
                    dp[0][j] = 1;
                    flag = 1;
                }
            }
        }
        // 初始化结束----------------------------------------------------
        for (int i = 1; i < text1.length(); i++) {
            for (int j = 1; j < text2.length(); j++) {
                if(text1.charAt(i)==text2.charAt(j)) 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]);
            }
        }
        return dp[text1.length()-1][text2.length()-1];
    }
}

dp[i][j]代表以i-1结尾的text1和以j-1结尾的text2 的最长公共子序列长度

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        // dp[i][j]代表以i-1结尾的text1和以j-1结尾的text2 的最长公共子序列长度
        int[][] dp = new int[text1.length()+1][text2.length()+1];
        for (int i = 1; i <= text1.length(); i++) {
            for (int j = 1; j <= text2.length(); j++) {
            	// 注意这里不是 i 和 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]);
            }
        }
        return dp[text1.length()][text2.length()];
    }
}

1035.不相交的线

完成

思路:

乍一看被吓到了,感觉判断线是否相交就不容易了,仔细分析发现其实就是找相同子序列。

和上一题的思路完全一样

代码

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int[][] dp = new int[nums1.length+1][nums2.length+1];

        for (int i = 1; i <= nums1.length; i++) {
            for (int j = 1; j <= nums2.length; j++) {
                if(nums1[i-1] == nums2[j-1]) dp[i][j] = dp[i-1][j-1]+1;
                else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
            }
        }
        return dp[nums1.length][nums2.length];
    }
}

53. 最大子序和

完成

思路:

贪心法做过。

动态规划 dp[i]代表以i结尾的数组中 最大子数组和,递推公式 dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]),需要注意的是,结果不一定从dp[len]处取,而是要在遍历过程中记录下最值。

代码

class Solution {
    public int maxSubArray(int[] nums) {
        // dp[i]代表以i结尾的数组中 最大子数组和
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        int res = nums[0];
        for (int i = 1; i < nums.length; i++) {
        	// 前面的累加结果保留   前面的结果丢弃,从nums[i]开始算
            dp[i] = Math.max(dp[i-1]+nums[i], nums[i]);
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值