最长递增子序列
题目
给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4.
解析
此题面试中非常常见,其实比较简单,一般面试中不要慌,按条理来一般都能答出 ^_^
N长度的数组,关于最长递增子序列有max(l(i))=max(l(i-1)),i>1, a[i]>a[i-1],这个关系式很重要
再来看假如N=1,那么l=1
如果N=2,有{16,24},那么可以发现l=2,因为max(l(0))=1,24>16,所以max(l(1))=max(l(0))+1
好了,其实我们可以维护一个N的辅助数组,每个值表示在当前元素下考虑后面的元素可能组成的最长递增子序列,比如刚刚为N=2,有f[0]=2,f[1]=1
现在来看一个长一点的数组:
a={3,18,7,14,10,12,23,41,16,24}
我们从后往前进行遍历(第一个索引为0)
a[9]=24,为最后一个元素,所以辅助数组b中f[9]=1 表示它以及它最后可能组成的最长递增子序列为1
则有
f={_,_,_,_,_,_,_,_,_,1}
a[8]=16,所以a[8]<a[9],故f[8]=2
f={_,_,_,_,_,_,_,_,2,1}
而a[7]=41>a[8],同时a[7]>10,所以考虑a[7]以后的元素它可能的最长递增子序列为1
f={_,_,_,_,_,_,_,1,2,1}
现在来看a[6]=23<a[41],暂时f[6]=f[7]+1=2 再来看a[6]<a[9] 所以f[6]=f[9]+1 还是2
f={_,_,_,_,_,_,2,1,2,1}
再来看一个a[5]=12,a[5]<a[6] 故f[5]=f[6]+1=3 再继续a[7],a[8],a[9]对比之后f[5]还是等于3
f={_,_,_,_,_,3,2,1,2,1}
.
.
.
f={6,3,5,3,4,3,2,1,2,1}
然后根据数组b取降序位置的索引6,5,4,3,2,1在a上打印出来即可
这里主要是介绍动态规划法:
貌似还有最大公共子序列法以及一个插入法来求
代码
1 | public static void main(String[] args) { |
打印结果
3
7
10
12
23
41
参考
http://qiemengdao.iteye.com/blog/1660229
本作品采用[知识共享署名-非商业性使用-相同方式共享 2.5]中国大陆许可协议进行许可,我的博客欢迎复制共享,但在同时,希望保留我的署名权