Vue3 diff的最長遞增子序列 算法詳解


const arr = [2, 1, 5, 3, 6, 4, 8, 9, 7]

function getSequence (arr) {

// const p = arr.slice() // [2, 1, 5, 3, 6, 4, 8, 9, 7]
const p = new Array(arr.length)
 
const result = [0]
 
let i, j, u, v, c
 
const len = arr.length // 9
 
for (i = 0; i < len; i++) {
 
const arrI = arr[i] // 某個元素
 
if (arrI !== 0) {
j = result[result.length - 1] // j是result中的最后一個元素 一開始是第0個元素

if (arr[j] < arrI) { // 如果arrI 大於 arr[j] 那么 把j存儲到p[i]
// 存儲在 result 更新前的最后一個索引的值
p[i] = j
result.push(i)
continue
}
 
u = 0 // result數組第0個元素
v = result.length - 1 // result數組的最后一個元素
 
// 二分搜索,查找比 arrI 小的節點,更新 result 的值
while (u < v) {
c = ((u + v) / 2) | 0
if (arr[result[c]] < arrI) {
u = c + 1
} else {
v = c
}
} // 最后的結果是找到u元素
 
if (arrI < arr[result[u]]) {
if (u > 0) {
p[i] = result[u - 1]
}
result[u] = i
}

}


}
 
u = result.length
v = result[u - 1]
 
// 回溯數組 p,找到最終的索引
while (u-- > 0) {
result[u] = v
v = p[v]
}
 
return result // 1 3 5 6 7
}
 
console.log(
// getSequence([5,3,4,0])
getSequence([2, 1, 5, 3, 6, 4, 8, 9, 7])
);

/*
。對於我們的例子而言,[2, 1, 5, 3, 6, 4, 8, 9, 7] 的最長子序列是 [1, 3, 4, 8, 9],
而我們求解的 [1, 3 ,5 ,6 ,7] 就是最長子序列中元素在原數組中的下標所構成的新數組。
*/

// 2, 1, 5, 3, 6, 4, 8, 9, 7
 
//i
//1步 2
//2步 1
//3步 1 5 p[2] =1 result:[1,2]
//4步 1 3 p[3] =1 result:[1,3] 更新index為3這個位置的元素的時候,前一個比他小的元素index是1
//5步 1 3 6 p[4] =3 result:[1,3,4]
//6步 1 3 4 p[5] =3 result:[1,3,5] 更新index為5這個位置的元素的時候,前一個比他小的元素index是3
//7步 1 3 4 8 p[6] =5 result:[1,3,5,6] 更新index為6這個位置的元素的時候,前一個比他小的元素index是5
//8步 1 3 4 8 9 p[7] =6 result:[1,3,5,6,7] 更新index為7這個位置的元素的時候,前一個比他小的元素index是6
//9步 1 3 4 7 9 p[8] =5 result:[1,3,5,8,7]
 

// 操作結束后,result中的最后一個元素一定是最大子序列的最后一個元素,
// 但是前面的值不一定正確,比如第9步的時候7將8替換掉了,已經不滿足子序列的條件了
// 所以需要數組p來記錄 數組p中記錄了第i次操作的時候,這次將要替換的元素的前一個元素(比它小的那個元素) 的index


// 最后進行一個回溯的操作
// 從result的最后一個元素開始,result中最后一個元素7肯定對應着最大子序列的最后一個,
// 去p數組中找,p數組中對應的這個元素,記錄了更新index為7的時候的前一個比他小的元素的index
// 向前回溯去找


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM