算法篇——动态规划最终篇 (js版)

动态规划做题顺序:

  • 确定 dpi 的意义
  • 确定递推公式
  • 初始化 dpi
  • 确定遍历顺序
  • 举例分析
300. 最长递增子序列

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

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

链接:力扣

解题思路:

本题主要考虑 元素的递增 ,因此确定 递推公式 时,也要考虑 当前遍历后的子序列的尾元素即将要遍历的元素 谁大,从而确定 递归序列的尾元素 是谁。

所以 dpi 就是表示 当前遍历后的子序列的长度。并且可以确定递推公式:

dpi = Math.max(dpi, dpj + 1) && numsi > numsj

这里的比较是针对取最大的 dpj 的子序列长度,不是将 dpi 和 dpj 进行比较,也可以理解成这样:

dpi = Math.max(dpj) + 1 && numsi > numsj && 0 <= j < i

再求解 Math.max(dpi) 即可

初始化长度为1,因为长度至少是1。

javascript 复制代码
var lengthOfLIS = function(nums) {
    if(nums.length == 1) return 1
    // 初始化都为1
    let dp = Array(nums.length).fill(1)
    // 递增子序列的长度
    let res = 1
    for(let i = 1; i < nums.length; i++) {
        for(let j = 0; j < i; j++) {
            // 获取最大的 dp[j]
            if(nums[i] > nums[j]) dp[i] = Math.max(dp[i], dp[j] + 1)
        }
        // 得到最长子序列长度
        res = Math.max(dp[i], res)
    }
    return res
}
674. 最长连续递增序列

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

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

链接:力扣

解题思路:

本题与上一题的不同之处在于,这道题强调 "连续",也就是说不比较 numsj 与 numsi(j 从0遍历到 i),而是比较 numsi 与 numsi - 1,也就无需双层循环。连续递增的子序列长度最小是1,所以初始化是1。递推公式是:

dpi = dpi - 1 + 1 && numsi > numsi - 1

javascript 复制代码
var findLengthOfLCIS = function(nums) {
    if(nums.length == 1) return 1
    // 初始化都为1
    let dp = Array(nums.length).fill(1)
    // 递增子序列的长度
    let res = 1
    for(var i = 1; i < nums.length; i++) {
        if(nums[i] > nums[i-1]) dp[i] = dp[i-1] + 1
        if (dp[i] > res) res = dp[i]
    }
    return res
}

718. 最长重复子数组

给两个整数数组 nums1nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度

链接:力扣

解题思路:

本题是要在连续最长子序列基础上,找到两个数组中的公共序列,因此,确定 dpij 是以 i - 1结尾的子序列1,和以 j - 1结尾的子序列2,最长重复子序列长度为 dpij。确定递推公式是:

dpij = dpi - 1j - 1 + 1 && nums1i - 1 == nums2j - 1

关于初始化:dpi0 和dp0j 在整个递推过程中没有实际意义,所以dpi0 和dp0j初始化为0。(这里需要初始化,方便递推)这里的遍历顺序可以先1后2或者先2后1都可以。

javascript 复制代码
var findLength = function(nums1, nums2) {
    const len1 = nums1.length, len2 = nums2.length
    // dp数组初始化,都初始化为0
    const dp = Array.from({ length: len1 + 1 }, () => Array(len2 + 1).fill(0))
    // 初始化最大长度为0
    let res = 0
    for(let i = 1; i <= len1; i++) {
        for(let j = 1; j <= len2; j++) {
            if(nums1[i - 1] == nums2[j - 1]) 
                dp[i][j] = dp[i - 1][j - 1] + 1
            res = Math.max(res, dp[i][j])
        }
    }
    return res
}
相关推荐
手写码匠3 分钟前
DeepSeek 函数调用实战:从零搭建一个会“动手“的 AI 助手
人工智能·深度学习·算法·aigc
前端精髓22 分钟前
React 更新 state 中的对象
javascript·react.js·ecmascript
果壳science1 小时前
《自然本源》如何实现狭义相对论的代数化
笔记·算法·几何学
可乐鸡翅yeah_1 小时前
hls.js 播放质量埋点实战,采集卡顿、起播、错误指标定位线上用户问题
开发语言·前端·javascript·ecmascript·音视频·m3u8·音视频在线播放
302wanger2 小时前
分享一个工作习惯:整点看即时消息
算法
洋不写bug3 小时前
排序(一)基础排序,插入|希尔|冒泡|直接选择排序详解
java·算法·排序算法·插入排序·冒泡排序·希尔排序·直接选择排序
牧羊人.3333 小时前
动手学深度学习 03 | 卷积神经网络实现手写数字识别
人工智能·深度学习·神经网络·算法·cnn
Bs_MoneyMagnet3 小时前
基于springboot+vue的宠物殡葬管理平台的设计与实现 源码+文档
java·javascript·vue.js·spring boot·后端·宠物
AgentMaster4 小时前
数据治理工具选型指南:一套可复用的四阶段决策框架
大数据·数据结构·人工智能·算法
尾善爱看海4 小时前
Vue 面试进阶篇:Composition API、插槽、自定义指令……8 个章节 + 高频面试题全解析
前端·javascript·vue.js·面试·vue