当前位置: 首页 > article >正文

vue3-diff算法-最长递增子序列

什么是最长递增子序列

最长递增子序列(LIS)是指在一个序列中,求出一个子序列,使得这个子序列元素的数值递增,且是原序列中长度最长的

vue3diff算法中的最长递增子序列

上篇文章分享vue3的diff算法原理最后一步处理其他情况(新增、卸载、移动)时提到一个关键点:最长递增子序列。
具体是怎么实现的呢?
demo:
在这里插入图片描述

在vue3是如何计算的?

整体思路

  • 动态规划
  • 二分查找
    – 在一组有序数组中折半查找,提高效率
  • 贪心算法
    – 在每一步选择中都采取当前状态下最优选择的算法设计策略,旨在通过局部最优解的累积来获得全局最优解。
    但可能会存在全局不是最优解的情况
  • 回溯修正
    – 为了解决贪心算法可能存在的问题。构造一个反向链表,每个节点记录上一个节点位置,最后回溯修正

以下demo为例:

第零位值为1,递增序列为0
在这里插入图片描述
第一位值为2,当时值大于前一个值,2 > 1,递增序列为1,前置指针0指向第0位,对应的值为1
在这里插入图片描述
第二位值为12,当时值大于前一个值,12 > 2,递增序列为2,前置指针1指向第1位,对应的值为2
在这里插入图片描述
第三位值为23,当时值大于前一个值,23 > 12,递增序列为3,前置指针2指向第2位,对应的值为12
在这里插入图片描述
第四位值为34,当时值大于前一个值,34> 23,递增序列为4,前置指针3指向第3位,对应的值为23
在这里插入图片描述
第五位值为3,当时值小于前一个值,3 < 34;
首先根据二分查找法
首位0,末位4,中间位为2,,这时中间位对应的值12 > 当前值3。
这时首位还是0,末位变为2,中间位为1,中间位对应值2 < 当前值3。
这时首位值变为2,末位不变还是2。
二分查找结束
那这时候2这个位置放12 还是 3 呢?
根据贪心算法思路:
应该要放最小值 3,
记录下标索引为5。同时记录当前值3的前置指针为第一位,对应值2
在这里插入图片描述
第六位值为4,当时值小于前一个值,3 < 34;
思路同上:二分查找 + 贪心算法
3这个位置需要放4,
记录下标索引为6。同时记录当前值4的前置指针为第五位,对应值3
在这里插入图片描述
到这一步,有没有发现上面的递增序列是有问题的呢?
这是因为贪心算法导致的偏差。贪心算法只会考虑当前算法的最优解,不在乎全局是否是最优解。
这时候就需要最后一步,回溯修正

回溯修正
从结果序列最后一位开始,也就是序列4:34开始倒序往前回溯
序列4:当前值34,前置指针3对应的值是23,;因此我们把34的前一位修正为23,对应的序列索引为3
在这里插入图片描述
序列3:当前值23,前置指针2对应的值是12,;因此我们把23的前一位修正为12,对应的序列索引为2
在这里插入图片描述
序列2:当前值2,前置指针1对应的值是2;和原来一致,不动
序列1:当前值0,和原来一致,不动
最后可以得到最终的结果如下:
在这里插入图片描述
以上就是vue3-diff算法-最长递增子序列的一个大致过程;
源码如下:


```javascript
// 给定一个数组,求最长递增子序列
function getSequence(arr: number[]): number[] {
  const p = arr.slice() // 复制原数组,用于构建递增序列
  const result = [0] // 定义结果序列,用于返回最终结果
  let i, j, u, v, c
  const len = arr.length
  for (i = 0; i < len; i++) { // 遍历原数组
    const arrI = arr[i]
    if (arrI !== 0) {
      j = result[result.length - 1] // 获取最后一位索引值
      if (arr[j] < arrI) {  // 判断当前值 > 最后一位
        p[i] = j  // 记录反向链表,执行最后一位
        result.push(i) // 插入序列表中
        continue
      }
      //二分查找
      u = 0
      v = result.length - 1
      while (u < v) {
        c = (u + v) >> 1
        if (arr[result[c]] < arrI) {
          u = c + 1
        } else {
          v = c
        }
      }
      if (arrI < arr[result[u]]) { // 找到第一位比当前大的值
        if (u > 0) {
          p[i] = result[u - 1] // 记录反向链表,指向序列第一位
        }
        result[u] = i  // 当前索引i替换原来位置
      }
    }
  }
  u = result.length
  v = result[u - 1]
  while (u-- > 0) { // 从后往前遍历,回溯修正
    result[u] = v
    v = p[v]
  }
  return result
}

http://www.kler.cn/a/469613.html

相关文章:

  • pymodubs TCP 无链接报错: pymodbus.exceptions.ConnectionException: Modbus Error
  • 密码学原理技术-第十一章-Hash Functions
  • 安卓漏洞学习(十六):unicorn在逆向中的使用
  • C# 设计模式(行为型模式):责任链模式
  • web系统漏洞攻击靶场
  • Eureka原理
  • 数据结构C语言描述8(图文结合)--哈希、哈希冲突、开放地址法、链地址法等实现
  • AndroidStudio环境版本管理
  • XIAO Esp32 S3 网络摄像头——3音视频监控
  • 2.1.7-1 io_uring的使用
  • 2025年,AI时代下的前端职业思考
  • 【网络安全 | 漏洞挖掘】绕过电子邮件确认实现预账户接管
  • 01——python (mac)安装
  • Redis两种主要的持久化方式是什么?
  • pytorch梯度上下文管理器介绍
  • 新疆乡镇界面图层arcgis格式shp数据有乡镇名称和编码2020年wgs84坐标无偏移数据内容测评
  • MySQL 04 章——运算符
  • 100万并发用户的分布式频道聊天系统
  • CSP初赛知识学习计划(第三天)
  • 【无线传感网】无线传感器网络安全
  • PostgreSQL 表达式
  • jenkins插件下载和从gitlab中拉取文件传送到虚拟机中
  • asp.net core框架搭建4-部署IIS/Nginx/Docker
  • 【AutoSAR】【底软自动化】Arxml自动配置平台
  • 青少年编程与数学 02-006 前端开发框架VUE 01课题、VUE简介
  • 二叉树相关的题,判断二叉树是否是单值二叉树,相同的树,对称二叉树,另一棵树的子树,KY11 二叉树遍历