问题描述: 随机生成小于等于n的自然数的一个序列,输出其最长递增子序列(任意一个即可)。
n 分别取 1000,3000,10000。
例: n=5 随机序列为 5 1 4 2 3,正确输出为1 2 3,即长度为3的递增子序列。
提示:参考LCS,思考能否达到时间复杂度(O(nlogn))
本题也采用了两种方案实现,第一种可以采用动态规划的思想,第二种就是书上的LCS求子序列的方法,通过对随机产生的数据然后通过快速排序进行排序,然后利用LCS,就可以求出结果,并且把它的所有结果都输出来,通过递归的方法可以把他的所有最长LCS求出来,但是存在问题,求出的解包含重复的解,通过设置遍历位visit[i]可以大大减小重复数,但是还是有,应该通过其他的数据结构可以实现,由于时间有限,就不在往下继续做。
方案1思想:
设f(i)表示L中以ai为末元素的最长递增子序列的长度。则有如下的递推方程:
这个递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。
输出结果如下:(采用方案一的方法)
方案2的输出结果如下:
数据较小时的输出结果如下:
注:这里产生的随机数和输入的数据大小相关,详细情况可以参照代码。
输出结果为1000的时候
输出结果为3000的时候
输出结果为10000的时候
思考题的回答:
提示:参考LCS,思考能否达到时间复杂度(O(nlogn))
答:可以实现,通过对方案一的改进
在计算每一个f(i)时,都要找出最大的f(j)(j<i)来,由于f(j)没有顺序,只能顺序查找满足aj<ai最大的f(j),如果能将让f(j)有序,就可以使用二分查找,这样算法的时间复杂度就可能降到O(nlogn)。于是想到用一个数组B来存储“子序列的”最大递增子序列的最末元素,即有B[f(j)] = aj。
注:代码上传在http://download.youkuaiyun.com/detail/liuyongvs2009/7077279