一道经典算法,也是vue3diff算法优化手段之一
function getSequence (arr) {
const result = []
// 记录前驱节点
const map = new Map()
for (let i = 0; i<arr.length; i++) {
const item = arr[i]
if (result.length === 0) {
result.push(i)
continue
}
// 如果当前这一项大于arr数组的最后一项,则直接push
const lastIndex = result[result.length - 1]
const lastItem = arr[lastIndex]
// 如果当前节点,大于 result的最后一个节点,则直接push
if (item > lastItem) {
// 记录前驱节点
map.set(i, lastIndex)
result.push(i)
continue
}
let left = 0
let right = result.length - 1
// 二分查找
while (left < right) {
// 计算出中间值
const mid = Math.floor((left + right) / 2)
const midItem = arr[result[mid]]
// 如果中间值小于item,则头指针向右走
if (midItem < item) {
left = mid + 1
}
// 否则尾指针 = 中间值
else {
right = mid
}
}
if (arr[result[left]] > item) {
if (left > 0) {
map.set(i, result[left - 1])
}
// 找到最合适的,把索引替换进去
result[left] = i
}
}
// 反向追踪
let l = result.length
let last = result[l - 1]
while (l > 0) {
l--
result[l] = last
last = map.get(last)
}
return result
}