广州天河建网站的公司网站信息发布和内容建设自查报告
广州天河建网站的公司,网站信息发布和内容建设自查报告,广州十大传媒公司,wordpress看后台浏览量一、先搞懂#xff1a;最长递增子序列#xff08;LIS#xff09;是什么#xff1f;
最长递增子序列#xff08;Longest Increasing Subsequence#xff0c;简称 LIS#xff09;是动态规划/贪心二分 领域的经典算法问题#xff0c;核心是找一个数组中「元素严格/非严格递…一、先搞懂最长递增子序列LIS是什么最长递增子序列Longest Increasing Subsequence简称 LIS是动态规划/贪心二分领域的经典算法问题核心是找一个数组中「元素严格/非严格递增、且不要求连续」的最长子序列。1. 核心概念通俗举例子序列数组中挑出部分元素顺序不变可间隔比如[10,9,2,5,3,7,101,18]的子序列可以是[2,5,7,101]递增子序列中后一个元素 前一个严格递增也可定义为 ≥ 非严格LIS满足递增的最长子序列比如上面数组的 LIS 长度是 4[2,3,7,101]或[2,5,7,101]。2. 两种核心解法重点讲 Vue3 用的高效版解法时间复杂度核心思路动态规划DPO(n²)用dp[i]表示以第 i 个元素结尾的 LIS 长度遍历每个元素对比前面所有元素更新 dp贪心二分O(n log n)维护一个“最小末尾数组”用二分找替换位置数组长度就是 LIS 长度Vue3 用这个贪心二分 通俗示例比如数组[2,5,3,7,11,8,10,13,6]初始化空数组tails []遍历每个元素2tails 空直接加 →[2]5比 tails 最后一个大加 →[2,5]3比 5 小找 tails 中第一个 ≥3 的位置索引1替换 5 →[2,3]7比 3 大加 →[2,3,7]11加 →[2,3,7,11]8替换 11 →[2,3,7,8]10替换 8 →[2,3,7,10]13加 →[2,3,7,10,13]6替换 7 →[2,3,6,10,13]最终 tails 长度 5就是 LIS 长度注意 tails 不是真正的 LIS只是长度相等。二、Vue3 中是否用到 LIS—— 不仅用了还很关键Vue3 在虚拟 DOM 的 diff 算法中核心使用了 LIS 算法优化「列表更新时的 DOM 移动逻辑」是提升 diff 性能的关键。1. 为什么需要 LIS背景当 Vue 渲染列表比如v-for且节点有key时更新列表比如增删、排序需要对比「老 vnode 数组」和「新 vnode 数组」核心目标是最小化 DOM 操作少移动、少删除/新增。比如老列表[a, b, c, d]key 对应新列表[b, d, a, c]。如果直接暴力更新会大量移动 DOM但如果找到「不需要移动的最长节点序列」只移动其他节点就能大幅减少操作。2. Vue3 中 LIS 的具体应用流程Vue3 的patchChildren方法处理子节点更新中针对「新老节点都是数组且有 key」的场景核心步骤步骤1建立映射筛选“可复用节点”遍历新节点数组记录「key → 新节点索引」的映射遍历老节点数组找到“新数组中也存在的节点”生成一个source数组source[i] 新数组中该老节点的索引不存在则为 -1。举例老节点[a(key:a), b(key:b), c(key:c), d(key:d)]新节点[b(key:b), d(key:d), a(key:a), c(key:c)]source 数组[2, 0, 3, 1]a 在新数组索引 2b 在 0c 在 3d 在 1。步骤2计算 source 数组的 LIS关键上面的 source 数组[2,0,3,1]其严格递增的 LIS是[0,1]对应老节点 b、d或[2,3]对应 a、c—— 这个 LIS 对应的老节点就是「不需要移动的最长序列」。步骤3基于 LIS 最小化 DOM 移动Vue3 会从后往前遍历新节点结合 LIS 结果LIS 中的节点位置已经“天然有序”无需移动非 LIS 中的节点只需要移动到目标位置而非删除重建。3. 为什么用 LIS因为 LIS 是「最长的无需移动序列」能最大程度减少 DOM 操作次数DOM 移动是高性能开销操作把 diff 算法的时间复杂度从 O(n²) 优化到 O(n log n)这也是 Vue3 diff 比 Vue2 更高效的核心原因之一。4. Vue3 中 LIS 的源码位置核心代码在runtime-core/src/patchChildren.ts中的getSequence函数就是贪心二分实现的 LIS简化版核心逻辑如下// Vue3 源码中 getSequence 函数简化版functiongetSequence(arr){constlenarr.length;constresult[0];// 存储 LIS 的索引不是值constpnewArray(len).fill(0);// 记录前驱节点用于还原完整 LISletlastIndex;letstart,end,mid;for(leti0;ilen;i){constvalarr[i];lastIndexresult[result.length-1];if(valarr[lastIndex]){p[i]lastIndex;result.push(i);continue;}// 二分找替换位置start0;endresult.length-1;while(startend){mid(startend)1;if(arr[result[mid]]val){startmid1;}else{endmid;}}if(valarr[result[start]]){if(start0){p[i]result[start-1];}result[start]i;}}// 还原完整的 LIS 索引letiresult.length;letlastresult[i-1];while(i--){result[i]last;lastp[last];}returnresult;}三、总结最长递增子序列LIS是找数组中「最长递增非连续子序列」的算法Vue3 用的是 O(n log n) 的贪心二分实现Vue3 在列表 diff 算法中核心依赖 LIS通过计算可复用节点索引数组的 LIS找到“无需移动的最长节点序列”最小化 DOM 操作提升更新性能这是 Vue3 对比 Vue2 diff 算法的重要优化点Vue2 未用 LISdiff 时间复杂度更高。