0
点赞
收藏
分享

微信扫一扫

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

天涯学馆 2024-08-08 阅读 27

1. LeetCode 1143.最长公共子序列

在这里插入图片描述
1.确定dp数组(dp table)以及下标的含义
dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
2.确定递推公式
主要就是两大情况: text1[i - 1] 与 text2[j - 1]相同,text1[i - 1] 与 text2[j - 1]不相同
1️⃣如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;
2️⃣如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。
即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
3.dp数组如何初始化
统一初始为0。
4.确定遍历顺序
从前向后,从上到下来遍历。

解法:
class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        //1.定义dp数组
        //dp[i][j]表示以下标i-1结尾的子串a和以下标j-1结尾的子串的最长公共子序列的长度
        int[][] dp = new int[text1.length()+1][text2.length()+1];
        //2.递推公式
        /**
        if (text1.charAt(i-1) == text2.charAt(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]);
        }
         */
        
        //3.初始化
        //4.遍历顺序
        int res = 0;
        for (int i=1;i<text1.length()+1;i++) {
            for (int j=1;j<text2.length()+1;j++) {
                if (text1.charAt(i-1) == text2.charAt(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]);
                }

                res = Math.max(res,dp[i][j]);
            }
        }

        return res;

    }
}

2. LeetCode 1035.不相交的线

在这里插入图片描述

解法:
class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        //本题等价于求解公共子序列(非连续)
        //1.定义dp数组
        //dp[i][j]表示以nums[i-1]结尾的序列和以nums2[j-1]结尾的序列的公共子序列长度
        int[][] dp = new int[nums1.length+1][nums2.length+1];
        //2.递推公式
        /**
        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]);
        }
         */
        //3.初始化
        //4.遍历顺序 从前往后
        int res=0;
        for (int i=1;i<nums1.length+1;i++) {
            for (int j=1;j<nums2.length+1;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]);
                }

                res = Math.max(res,dp[i][j]);
            }
        }

        return res; 
    }
}

3. LeetCode 53. 最大子序和

在这里插入图片描述

思路:
1.确定dp数组(dp table)以及下标的含义
dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]。
2.确定递推公式
dp[i]只有两个方向可以推出来:
nums[i]+dp[i - 1],即:nums[i]加入当前连续子序列和
nums[i],即:从头开始计算当前连续子序列和
一定是取最大的,所以dp[i] = max(nums[i]+dp[i - 1], nums[i]);
3.dp数组如何初始化
dp[0] = nums[0]。
4.确定遍历顺序
递推公式中dp[i]依赖于dp[i - 1]的状态,需要从前向后遍历。
5.返回值
dp数组中的最大值。

解法:
class Solution {
    // // 贪心
    // public int maxSubArray(int[] nums) {
       
    //     int res = nums[0];
    //     int count = 0;
    //     for (int i=0;i<nums.length;i++) {
    //         count += nums[i];
    //         if (count > res) {// 取区间累计的最大值(相当于不断确定最大子序终止位置)
    //             res = count;
    //         }
    //         if (count <= 0) {
    //             count = 0;// 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
    //         }
    //     }

    //     return res;
    // }

    // 动态规划
    public int maxSubArray(int[] nums) {
        //1.定义dp数组 
        //dp[i]表示以nums[i]结尾的最大连续子数组之和
        int[] dp = new int[nums.length];
        //2.递推公式
        //dp[i] = Math.max(nums[i]+dp[i-1],nums[i]);
        //3.初始化
        dp[0]=nums[0];
        //4.遍历顺序 从前往后
        int res = nums[0];
        for (int i=1;i<nums.length;i++) {
            dp[i] = Math.max(nums[i]+dp[i-1],nums[i]);
            res = Math.max(res,dp[i]);
        }

        return res;
    }
}

4. LeetCode 392.判断子序列

在这里插入图片描述

解法:
class Solution {
    public boolean isSubsequence(String s, String t) {
        char[] nums1 = s.toCharArray();
        char[] nums2 = t.toCharArray();
        //1.定义dp数组
        //dp[i][j]表示以nums[i-1]结尾的子序列和以nums[j-1]结尾的子序列的最长公共子序列长度
        int[][] dp = new int[nums1.length+1][nums2.length+1];
        //2.递推公式
        /**
        if (nums[i-1]==nums[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]);
        }
         */
        //3.初始化
        //4.遍历顺序
        int res = 0; 
        for (int i=1;i<nums1.length+1;i++) {
            for (int j=1;j<nums2.length+1;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]);
                }
                res=Math.max(res,dp[i][j]);
            }
        }

        return res==nums1.length; 
        
    }
}
举报

相关推荐

0 条评论