最长上升子序列(LIS)的n*log(n)求法

方法:

对于某个序列,设一个数组,将序列第一个数放入,然后再一个一个判断序列下一位,如果大于当前数组的末尾元素,则加入数组,否则利用二分法找到第一个大于等于当前数的元素并替换,最后这个数组的长度len就是最长上升子序列的长度。

正常DP求LIS的复杂度是O(n^2),如果面对非常大量的数据的回收怎么办呢?这时候就可以用到这种求法(但是这中求法只能求出个数而不能求出正确的子序列)

这种求法实际上已经不是DP了,比较像贪心,数组代表的是“可能性”,每次替换都是将“可能性”增大,但是最后结果其实并不是最长上升子序列。

引用一个别人的例子:

  有以下序列A[]=3 1 2 6 4 5 10 7,求LIS长度。

  我们定义一个B[i]来储存可能的排序序列,len为LIS长度。我们依次把A[i]有序地放进B[i]里。(为了方便,i的范围就从1~n表示第i个数)

  A[1]=3,把3放进B[1],此时B[1]=3,此时len=1,最小末尾是3

  A[2]=1,因为1比3小,所以可以把B[1]中的3替换为1,此时B[1]=1,此时len=1,最小末尾是1

  A[3]=2,2大于1,就把2放进B[2]=2,此时B[]={1,2},len=2

  同理,A[4]=6,把6放进B[3]=6,B[]={1,2,6},len=3

  A[5]=4,4在2和6之间,比6小,可以把B[3]替换为4,B[]={1,2,4},len=3

  A[6]=5,B[4]=5,B[]={1,2,4,5},len=4 

  A[7]=10,B[5]=10,B[]={1,2,4,5,10},len=5

  A[8]=7,7在5和10之间,比10小,可以把B[5]替换为7,B[]={1,2,4,5,7},len=5

原文地址:https://www.cnblogs.com/Lightfall/p/9308777.html