js使用动态数组解决子序列问题入门

涉及力扣题目:
300.最长递增子序列
674. 最长连续递增序列
718. 最长重复子数组

求子序列相关问题往往是要求一些累增数量问题,如递增连续或不连续子序列长度,公共连续子序列。这类问题往往有一个显著的特点那就是它的结果在瞒足题目条件下的结果就是前一项加一,那么我们在解决此类问题只需要模拟出一个遍历以及记录的情况。

比如题目一:

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组
[0,3,1,6,2,2,7] 的子序列。

我们要求不连续的递增子序列的最大长度。
我们可以从头开始遍历,如果在遍历中的元素是要大于前面的元素的,那么前面这个元素原有的子序列长度再加上在遍历的元素也就是加一就完成了动态数组的更新。
定义数组:
一个一维数组,值是以i下标为结尾的最大递增子序列长度。
推导公式:
遍历前i个前元素,只要大于就更新加一

for(let j = 0; j < i; j++) {
            if(nums[i] > nums[j]) {
                dp[i] = Math.max(dp[i], dp[j]+1);
            }
    }

初始化:
因为单独一个元素就算是一个子序列,所以最小长度为1

完整代码:

const lengthOfLIS = (nums) => {
    let dp = Array(nums.length).fill(1);//初始化
    let result = 1;//记录数组中最大值

    for(let i = 1; i < nums.length; i++) {
        for(let j = 0; j < i; j++) {
            if(nums[i] > nums[j]) {
                dp[i] = Math.max(dp[i], dp[j]+1);
            }
        }
        result = Math.max(result, dp[i]);
    }

    return result;
};

题目二:

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i+ 1] ,那么子序列 [nums[l], nums[l + 1], …, nums[r - 1], nums[r]] 就是连续递增子序列。

与题目一不同的是求连续的递增。

这题最先想到的肯定是双指针一前一后遍历。
而我们也可以使用动态数组来记录最大。只需要满足nums[i]>nums[i-1]即大于前一项,那么就加一

完整代码:

var findLengthOfLCIS = function(nums) {
    let dp =Array(nums.length).fill(1)
    for(let i=1;i<nums.length;i++){
        if(nums[i]>nums[i-1]){
            dp[i]=dp[i-1]+1
        }
        
    }
    return Math.max(...dp)
};

题目三:

给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的连续子数组的长度。

这题看起来好像有点难度,其实只是因为它从模拟一维的情况变成了二维而已。
我们可以想象在一个二维数组中行是A的每个元素,列式B的每个元素,那么遍历这个二维矩阵,他们中只要行的元素等于列就是满足题意的局部条件,同时若他们的上一行上一列也是相等的那么长度就是二,以此类推。最终整个二维数组最大的元素就是结果。这里有的问题就是为什么它会是左上的对角呢?原因很简单它要求同时在A和B上连续!

完整代码:

const findLength = (A, B) => {
    // A、B数组的长度
    const [m, n] = [A.length, B.length];
    // dp数组初始化,都初始化为0
    const dp = new Array(m + 1).fill(0).map(x => new Array(n + 1).fill(0));
    // 初始化最大长度为0
    let res = 0;
    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            // 遇到A[i - 1] === B[j - 1],则更新dp数组
            if (A[i - 1] === B[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            }
            // 更新res
            res = dp[i][j] > res ? dp[i][j] : res;
        }
    }
    // 遍历完成,返回res
    return res;
};

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值