本文分步分析最长递增子序列的求法,解析的是vue中的getSetuence函数,以下是具体过程
找出递增序列
首先找到当前的单调递增序列,设置一个result数组,判断新加入的元素是否比当前最后一个元素大,是的话就push到result中来,得出来一个递增序列[1,4,8],但此时的序列并非最长序列,最长序列应为[1,4,6,7]
js
function a(arr){
let result = [0]
for(let i = 0;i<arr.length;i++){
let arrI = arr[i]
let resultLast = result[result.length-1]
if(arrI > arr[resultLast]){
result.push(i)
}
return result.map(item=>arr[item])
}
let arr = [1,4,8,3,6,2,7]
console.log(a(arr));//[1,4,8]
找出最长递增子序列长度
接下来参考力扣300的解法,我们先设法找出最长递增子序列的长度
每次遍历时如果取出的值没有result最后一个值大,那么就找到数组中比当前值大的最小数值并替换之
如下
遍历到2时
数组对应的值 【1、4、8】此时1为数组中比2小的最大值,则数组改为【1、2、8】
同理下次循环后为【1、3、8】
以此类推【1、3、6】、【1、2、6】、【1、2、6、7】
其最长递归子序列的长度则为4,需要注意的是【1、2、6、7】并非所求数组的最长递增子序列,其排序已不是原数组的排序顺序,这点在最后会解决,现在来实现上述过程
js
function a(arr){
let result = [0]
for(let i = 0;i<arr.length;i++){
let arrI = arr[i]
let resultLast = result[result.length-1]
if(arrI > arr[resultLast]){
result.push(i)
continue
}
// 二分法查找比当前值大的最小值
let start = 0,end = result.length-1,middle = Math.floor(start - (start-end)/2)
while(start < end){
middle = Math.floor(start - (start-end)/2)
if(arrI <= arr[result[middle]]){
end = middle
}else{
start = middle+1
}
}
// 此时start===end
result[end] = i
}
return result.map(item=>arr[item])
}
let arr = [1,4,8,3,6,2,7]
console.log(a(arr));//【1、2、6、7】
纠正
经过上述两个步骤之后,我们会发现虽然排出了序列,但是显而易见,这个排序是有问题,问题在于我们每次比较完成之后就将后面的值插入到了前面,导致混乱
我们的解决方法是利用一个数组,记录下当前位置的前一个排序位置,从而使得我们可以往前找到我们需要的值
代码如下
js
function a(arr){
// 添加数组p进行记录
let result = [0],p=arr.slice()
for(let i = 0;i<arr.length;i++){
let arrI = arr[i]
let resultLast = result[result.length-1]
if(arrI > arr[resultLast]){
result.push(i)
// 在当前位置记录前一个的索引
p[i] = resultLast
continue
}
let start = 0,end = result.length-1,middle = Math.floor(start - (start-end)/2)
while(start < end){
middle = Math.floor(start - (start-end)/2)
if(arrI <= arr[result[middle]]){
end = middle
}else{
start = middle+1
}
}
result[end] = i
// 这里也需要同步记录
p[i] = result[end-1]
}
// 对数据进行纠正
let n = result.length,last = result[n-1]
while(n-- > 0){
result[n] = last
last = p[last]
}
return result.map(item=>arr[item])
}
let arr = [1,4,8,3,6,2,7]
console.log(a(arr));//[1, 3, 6, 7]