算法练习day46

88 阅读2分钟

一、最长公共子序列

这里的子序列和上一题的子数组不同点在于,这里的子序列不要求连续,只要求相对顺序

五部曲

  1. 确定dp数组以及含义,dp[i][j],表示0到i-1,的字符串text1和0到j-1的字符串text2之间的最长公共子序列
  2. 递推公式
    1. 如果text1[i-1] === text2[j-1],则dp[i-1][j-1] + 1
    2. 如果text1[i-1] !== text2[j-1],则Math.max(dp[i-1][j], dp[i][j-1])
  3. 初始化,统一初始化为0
  4. 遍历顺序,从前到后
  5. 举例推导

时间复杂度: O(n * m),其中 n 和 m 分别为 text1 和 text2 的长度 空间复杂度: O(n * m)

/**
 * @param {string} text1
 * @param {string} text2
 * @return {number}
 */
var longestCommonSubsequence = function(text1, text2) {
    let dp = new Array(text1.length + 1).fill(0).map(_ => new Array(text2.length + 1).fill(0))
    for(let i = 1; i <= text1.length;i++) {
        for(let j = 1; j <= text2.length; j++) {
            if(text1[i-1] === text2[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[text1.length][text2.length]
};

二、不相交的线

本题最大连线数,其实就是求两个字符串的最长公共子序列的长度,和上题完全一样

三、最大子序和

找到最大和的连续子数组

五部曲

  1. dp数组的含义,dp[i],i结尾的最大连续子数组和
  2. 确定递推公式,Math.max(nums[i] + dp[i-1], nums[i]),其实就是这两种情况的最大值
  3. 确定遍历顺序,从前往后
  4. 初始值,dp[0] = nums[0]
  5. 举例推导

最终返回的是dp中最大的值,而不是最后一个值

var maxSubArray = function (nums) {
    let dp = []
    dp[0] = nums[0]
    let result = nums[0]
    for (let i = 1; i < nums.length; i++) {
        dp[i] = Math.max(dp[i - 1] + nums[i], nums[i])
        result = Math.max(result, dp[i])
    }
    return result
};