算法Day53 | 1143.最长公共子序列,1035.不相交的线, 53. 最大子序和

1143.最长公共子序列

题目链接:1143.最长公共子序列
dp数组[0, i - 1][0, j - 1]范围的最长公共子序列表示为dp[i][j]

递推公式

dp[i][j] = (text1[i - 1] == text2[j - 1])
            ? dp[i - 1][j - 1] + 1
            : max(dp[i - 1][j], dp[i][j - 1]);

如果text1[i - 1]text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;
如果text1[i - 1]text2[j - 1]不相同,那就看看text1[0, i - 2]text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]text2[0, j - 2]的最长公共子序列,取最大的。

初始化
dp[i][0] = dp[0][j] = 0,其他都是0

根据递推公式可知,dp[i][j]都是之前的状态dp[i-1][j-1]dp[i-1][j]dp[i][j-1]推出的,因此最终输出dp.back().back()即可

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
        for (int i = 1; i <= text1.size(); ++i) {
            for (int j = 1; j <= text2.size(); ++j) {
                dp[i][j] = (text1[i - 1] == text2[j - 1])
                           ? dp[i - 1][j - 1] + 1
                           : max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        return dp.back().back();
    }
};

一维数组

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<int> dp(text2.size() + 1, 0);
        for (int i = 1; i <= text1.size(); ++i) {
            int prev = 0;
            for (int j = 1; j <= text2.size(); ++j) {
                int temp = dp[j];
                dp[j] = (text1[i - 1] == text2[j - 1])
                        ? prev + 1
                        : max(dp[j], dp[j - 1]);
                prev = temp;
            }
        }
        return dp.back();
    }
};

对代码进行进一步解释:

  1. 首先,创建一个大小为text2.size() + 1的整数型向量dp,并将所有元素初始化为0。dp向量用来保存子问题的最优解。

  2. 接下来,通过两层嵌套循环来计算最长公共子序列的长度。外层循环遍历text1字符串的每一个字符,内层循环遍历text2字符串的每一个字符。

  3. 在外层循环的每一次迭代中,初始化变量prev为0。prev用来保存上一次内层循环中dp向量的值,即上一个元素的对角线的值。

  4. 在内层循环的每一次迭代中,首先保存dp[j]到变量temp中。

  5. 然后,判断text1[i - 1]text2[j - 1]是否相等。如果相等,说明两个字符可以构成公共子序列的一部分,所以最长公共子序列的长度为prev + 1,并将该值保存到dp[j]中。如果不相等,则最长公共子序列的长度为dp[j]dp[j - 1]中的较大值,再将该值保存到dp[j]中。

  6. 最后,将temp的值赋给prev,以备下一次迭代使用。

  7. 循环结束后,dp.back()表示dp向量中最后一个元素的值,即最长公共子序列的长度。最后,将该值作为函数的返回值。


1035.不相交的线

题目链接:1035.不相交的线
相同数字连线就是数字顺序问题,就是子序列。因此和上一题代码思路一样。

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

53. 最大子序和

题目链接:53. 最大子序和
dp数组:以i结尾的最大连续子序列和

递推公式
dp[i] = max(dp[i - 1] + nums[i], nums[i])

初始化
dp[0] = nums[0]

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int> dp(nums.size(), nums[0]);
        int res = nums[0];//保存为nums.size() == 1时的结果。
        for (int i = 1; i < nums.size(); ++i) {
            dp[i] = max(dp[i - 1] + nums[i], nums[i]);
            res = max(res, dp[i]);
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值