动态规划(2)-最长增序列
来源:互联网 发布:苹果手机4g网络不稳定 编辑:程序博客网 时间:2024/05/02 08:53
最长增序列(Longest Increasing Subsequence,LIS )给定一个数列,从中删掉任意若干项剩余的序列叫做它的一个子序列,求它的最长的子序列,满足子序列中的元素是单调递增的。
例如给定序列{1,6,3,5,4},答案是3,因为{1,3,4}和{1,3,5}就是长度最长的两个单增子序列。
暴力枚举
C(n,0)+C(n,1)+…+C(n,n)=
其实只需要考虑加入的数比之前加入的最后一个数大就可以了。而最长的意思是数的个数最多,我们只要知道数的总个数就可以了,没必要知道具体有哪些数。
动态规划
假设这个序列是
以下记录算法过程加深对算法理解:
j=0,f[1]=1j=0,f[2]=1j=1,f[2]=2j=0,f[3]=1j=1,f[3]=1j=2,f[3]=1j=0,f[4]=1j=1,f[4]=1j=2,f[4]=1j=3,f[4]=2j=0,f[5]=1j=1,f[5]=1j=2,f[5]=1j=3,f[5]=2j=4,f[5]=3j=0,f[6]=1j=1,f[6]=2j=2,f[6]=3j=3,f[6]=3j=4,f[6]=3j=5,f[6]=4j=0,f[7]=1j=1,f[7]=2j=2,f[7]=3j=3,f[7]=3j=4,f[7]=3j=5,f[7]=4j=6,f[7]=4j=0,f[8]=1j=1,f[8]=2j=2,f[8]=3j=3,f[8]=3j=4,f[8]=3j=5,f[8]=4j=6,f[8]=4j=7,f[8]=5
回溯过程如下图:
先从f中找到最大的那个i,其在A中对应的元素就是LIS的最后一个,然后一项一项不断向f[:i]中找最大的即可。
为了方便代码只找一个LIS(所有最大递增子序列中,最大值下标最小,由index函数决定)实际上可以找多个LIS,那就是最大的那个i有多个的情况。
时间复杂度O(
以{1,6,3,5,4}为例子,我们想像考虑5的时候,之前有两个长度为2的子序列{1,6}和{1,3},那么哪个更“好”呢?显然后者更好,因为3比6小,以3结尾的序列更容易在后面接上一个数。也就是说一个序列,长度为n的递增子序列可能不止一个,但是所有长度为n的子序列中,有一个子序列是比较特殊的,那就是最大元素最小的递增子序列。这就类似贪心策略,那么问题明了了,开始我们只有一个长度为0的单调子序列,末尾大小认为是-∞,这个序列可以用栈来存储(对python来说list就是栈)。对于A里面的元素
最后LIS的长度就是栈长度。
整个算法过程如图所示,这里省略了最左边的-INF:
那如何找到具体一个子序列呢?
观察图可以发现,
[ 3]
[ 3, 4]
[1, 2, 3]
[ 1, 2, 3, 7]
[1, 2, 3, 6, 7]
均是stack入栈后的序列,只要打印最后一个入栈后的队列即可得到这个序列的LIS,当然打印LIS还有其他办法,大家可以分享。
对应代码:
#LIS O(nlogn)import sysA=[3,4,1,2,3,7,6,7]n=len(A)stack=[-sys.maxsize]for i in range(n): if A[i]>stack[-1]:#如果比栈顶元素大那么加入栈 stack.append(A[i]) res=stack.copy() else:#二分检索栈中比A[i]大的第一个数 low=0;high=len(stack)-1 while low<=high: mid=(low+high)//2 if A[i]>stack[mid]: low=mid+1 else: high=mid-1 stack[low]=A[i]print (res[1:])#打印LISprint(len(stack)-1)#打印LIS长度
- 动态规划(2)-最长增序列
- 动态规划2:最长非升子序列和最长非降子序列
- 动态规划(2)-最长递增子序列
- 动态规划----最长子序列
- 【最长子序列 动态规划】
- 动态规划----最长子序列
- 动态规划-最长非降子序列
- 最长单增子序列-动态规划
- 动态规划----各种最长序列
- 动态规划-最长非降子序列
- 动态规划 最长非降子序列
- 最长子序列--动态规划
- 动态规划----求一个数组的最长增序列
- 动态规划学习笔记2(最长公共子序列)
- [动态规划-2] 最长公共子序列-Longest Common Subsequence
- (2)最长不下降子序列问题____动态规划
- 动态规划学习与实例(2) 最长公共子序列
- 动态规划问题(2)-最长上升子序列
- Android开源项目推荐之「图片加载到底哪家强」
- 致JavaScript也将征服的物联网世界
- EventBus使用详解(一)——初步使用EventBus
- PHP产生不重复随机数的5个方法总结
- secureCRT使用问题记录
- 动态规划(2)-最长增序列
- 二维数组输出
- shell处理mysql增、删、改、查
- 一个五年 Android 开发者百度、阿里、聚美、映客的面试心经
- k-近邻算法(k-Nearest Neighbor, kNN)
- android的消息处理机制——Looper,Handler,Message
- CentOS7下的网络设定方法
- 转载:做技术真的没前途前途吗?
- 网上知识点汇总一