diff算法_基于最长公共子序列(LCS)的diff算法

本文探讨了动态规划在解决最优化问题中的应用,特别是最短编辑距离算法在前端框架如Vue和React中的实现。作者分析了不同类型的Diff算法,包括最长递增子序列(LIS)和最长公共子序列(LCS),并指出LCS能简化代码实现,但要达到最短编辑距离仍需复杂度优化。文章强调性能与简洁度之间的平衡,并提出未来研究方向将基于LCS的Diff算法。
摘要由CSDN通过智能技术生成

575da54995f470a189d738a88706f7e8.png

大家好我是 132,昨天为了面试看了一下动态规划(虽然面试没考到),但还是有很多收获

反正不管怎么样,我只得出了一个结论,那就是,动态规划是用来解决最xx的问题的

很明显,diff 算法就是很典型的……最短编辑距离

diff 算法其实非常多,比较典型的主要有三种,一种是 preact 的试探下一个算法,一种是 snabbdom 的两端遍历的方法,再就是 inferno 的最长递增子序列的算法

前两种用于链表是在太过于困难,注意链表的特点,它不是数组,不能很方便地取到首尾节点,也不是递归,和递归时候的参数完全不同,所以两端遍历这种严重依赖首尾,索引的算法,用不到链表中

所以没办法只能用 inferno 的算法了,不过幸好,inferno 的算法似乎更简单

最长递增子序列(lis)

inferno 的算法,核心思想就是寻找一个最长递增子序列,然后这部分节点保持不动,其他的节点进行往前插

举个例子

 - A: [1 2 3 4] // 旧的
 - B: [4 1 2 3] // 新的
 - P: [3 0 1 2] // 索引队列
 - LIS: [0 1 2] // 最长递增子序列

我们只需要用一个数组记录变化后的索引队列,然后寻找这个索引队列的最长递增子序列

完美,然后就变成一个动态规划的问题了……

然后最终我们找到了最长递增子序列之后,这些就保持位置不动,然后其他的进行插入

即可

最长公共子序列(lcs)

虽然使用最长递增子序列是没毛病的,但是这个实现的代码量简直不忍直视

vue3 甚至都达到了 2000 多行:https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/renderer.ts

同样是抄袭,俺一定要抄成 200 行!

所以复制粘贴是不行了,我们得继续抽象

答案是最长公共子序列,这样我们可以直接比对两个数组序列,而不需要维护 p 数组了

但是即便是 lcs,要想实现 nlogn 的复杂度,还是要将其转化为 lis 问题才行

同时还有一点,因为 vue,nerv,inferno,ivi 是基本雷同的

fre 不想雷同,虽然我也不去自创算法,但是我至少代码架构不去复制粘贴

时间复杂度

大家可能会对时间复杂度有疑问,然后动态规划不是 O(n*) 吗,那 react 说的 O(n) 是咋回事

时间复杂度,是针对 js 代码的,也就是你写的代码是 O(n),虽然 react 的代码时间复杂度低,但是它根本无法做到最短编辑距离呀

要想真正做到最短编辑距离,是不可能 O(n) 的,撑死就是优化动态规划,比如使用二分查找,让它变成 O(nlogn)

当然这些都不是重点,我们既然决定动这个算法,肯定要换个追求:

编辑距离 > 时间复杂度

实现思路

之后再说

总结

算法都是有目的性的,比如我们为了实现最短,那么它的时间复杂度就不可能最低

相反,如果我们放弃目标,求个不短的,自然实现简单,复杂度也很低

性能是一个很难量化的东西,大多数时候我们要的不是理论极限值而是一个刚刚好的值

当然,由于你们都不用 fre,那还谈什么刚刚好,作为一个没人用的框架,就应该只空谈理论极限!

未来很长一段时间,基于 lcs 的 diff 算法将会是 fre 的研究方向,大家有兴趣的可以一起来玩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值