最长递增子序列LIS
Posted 血影雪梦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长递增子序列LIS相关的知识,希望对你有一定的参考价值。
本总结是是个人为防止遗忘而作,不得转载和商用。
题目
给定长度为N的数组A,计算A的最长的单调递增的子序列(不一定连续)。
如:给定数组A5,6,7,1,2,8,则A的LIS为5,6,7,8,长度为4。
方法一
使用LCS解LIS问题:
原数组为A 5, 6, 7, 1, 2, 8
排序后:A’1, 2, 5, 6, 7, 8
因为,原数组A的子序列顺序保持不变,而且排序后A’本身就是递增的,这样,就保证了两序列的最长公共子序列的递增特性。如此,若想求数组A的最长递增子序列,其实就是求数组A与它的排序数组A’的最长公共子序列。
PS:LCS见http://blog.csdn.net/xueyingxue001/article/details/52916554
方法二 - 动态规划
如果直接由An得出结论,如:根据8得出LIS为5678是不好做的,那么就把n降一将,先A0=5开始,求以5结尾的LIS,然后从A0推出A1,即:以6结尾的LIS,然后从A0和A1分别推出A2,即:以7结尾的LIS,以此类推,下面举个例子。
求数组1, 4, 6,2, 8, 9, 7的LIS。
假设当前已经求出了A0 ~A5:
A0:当前已经求出以1结尾的LIS时1,长度为1;
A1:以4结尾的LIS时14,长度为2;
A2:以6结尾的LIS为146,长度为3;
A3:以2结尾的LIS为12,长度为2;
A4:以8结尾的LIS为1468,长度为4;
A5:以9结尾的LIS为14689,长度为5;
现在求Ai+1(A6),即求以7结尾的最长LIS:
A0->A6:将7放在1后面可以,此时长度为2;
A1->A6:将7放在14后面可以,此时长度为3;
A2->A6:将7放在146后面可以,此时长度为4;
A3->A6:将7放在12后面可以,此时长度为3;
A4->A6:将7放在1468后面不可以,因为7比8小;
A5->A6:同上,不行。
那A0->A6、A1->A6、A2->A6、A3->A6中最大的是谁呢?是A2->A6,因此A2->A6的结果1467就得到了。
话说这题单纯肉眼就能得出结论,因此这个的更重要的意义是学习动态规划。
方法三 - 贪心法
求数组1, 4, 6, 2, 8, 9, 7的LIS。1,创建一个足够大的缓冲区
2,从左向右取:
第一个1放在缓冲区
第二个4放在缓冲区末尾,放上去后让4和前面的依次比较,如果a[i]=4> a[j],那就让a[j+1] = a[i],这里不存在此情况,所以缓冲区还是14
第三个6放在缓冲区末尾,然后比较,缓冲区为146
第四个2放在缓冲区末尾,然后比较,当2和1比较时,因为2>a[0]=1,所以令a[0+1]=2,所以缓冲区为126
同理把8、9、7也依次代入,最后缓冲区为12679
3,到此所有数遍历完毕,当然现在缓冲区存留的12679不是LIS,不过!长度是LIS的长度!
这是为什么?
是这样,首先从左向右取的时候,146的LIS是146没问题吧,而当遍历到1462时,1462的LIS还是146,2没用,于是我就想个办法把2替换到数组中,这样数组的长度就一定是LIS的长度了(虽然内容不是LIS)
话说,刚才在第二步介绍的比较可以用折半查找,不用一个个比较。
再话说,当从12689得出12679时不需要知道之前的内容,所以这个本质上是贪心。
以上是关于最长递增子序列LIS的主要内容,如果未能解决你的问题,请参考以下文章