找出n个数组成的最长单调递增子序列( 动态规划O(nlogn) )
来源:互联网 发布:软件项目交付流程 编辑:程序博客网 时间:2024/05/10 13:12
题目:
给出一个由n个数组成的序列x[1..n],找出它的最长单调上升子序列。即求最大的m和a1,a2……,am,使得a1<a2<……<am且x[a1]<x[a2]<……<x[am]。
分析:
这也是一道动态规划的经典应用。一种动态规划的状态表示描述为:
m[i],1≤i≤n,表示以x[i]结尾的最长上升子序列的长度,则问题的解为 max{m[i],1≤i≤n},
状态转移方程和边界条件为:
m[i]=1+max{0, m[k]|x[k]<x[i] , 1≤k<i }
同时当m[i]>1时,令p[i]=k,表示最优决策,以便在计算出最优值后构造最长单调上升子序列。
上述算法的状态总数为O(n),每个状态转移的状态数最多为O(n),每次状态转移的时间为O(1),所以算法总的时间复杂度为O(n2)。
算法改进:
我们先来考虑以下两种情况:
1、若x[i]<x[j],m[i]=m[j],则m[j]这个状态不必保留。
因为,可以由状态m[j]转移得到的状态m[k] (k>j,k>i),必有x[k]>x[j]>x[i],则m[k]也能由m[i]转移得到;另一方面,可以由状态m[i]转移得到的状态m[k] (k>j,k>i),当x[j]>x[k]>x[i]时,m[k]就无法由m[j]转移得到。
由此可见,在所有状态值相同的状态中,只需保留最后一个元素值最小的那个状态即可。
2、若x[i]<x[j],m[i]>m[j],则m[j]这个状态不必保留。
因为,可以由状态m[j]转移得到的状态m[k] (k>j,k>i),必有x[k]>x[j]>x[i],则m[k]也能由m[i]转移得到,而且m[i]>m[j],所以m[k]≥m[i]+1>m[j]+1,则m[j]的状态转移是没有意义的。
综合上述两点,我们得出了状态m[k]需要保留的必要条件:
不存在i使得:x[i]<x[k]且m[i]≥m[k]。
于是,我们保留的状态中不存在相同的状态值,且随着状态值的增加,最后一个元素的值也是单调递增的。
也就是说,设当前保留的状态集合为S,则S具有以下性质D:
对于任意i∈S, j∈S, i≠j有:m[i]≠m[j],且若m[i]<m[j],则x[i]<x[j],否则x[i]>x[j]。
下面我们来考虑状态转移:假设当前已求出m[1..i-1],当前保留的状态集合为S,下面计算m[i]。
1、若存在状态k∈S,使得x[k]=x[i],则状态m[i]必定不需保留,不必计算。
因为,不妨设m[i]=m[j]+1,则x[j]<x[i]=x[k],j∈S,j≠k,所以m[j]<m[k],则m[i]=m[j]+1≤m[k],所以状态m[i]不需保留。
2、否则,m[i]=1+max{m[j]| x[j]<x[i], j∈S}。
我们注意到满足条件的j也满足x[j]=max{x[k]|x[k]<x[i], k∈S}。同时我们把状态i加入到S中。
3、若2成立,则我们往S中增加了一个状态,为了保持S的性质,我们要对S进行维护,若存在状态k∈S,使得m[i]=m[k],则我们有x[i]<x[k],且x[k]=min{x[j]|x[j]>x[i], j∈S}。于是状态k应从S中删去。
于是,我们得到了改进后的算法:
For i:=1 to n do
{ //找出集合S中的x值不超过x[i]的最大元素k;
if x[k]<x[i] then
{
m[i]:=m[k]+1;
//将状态i插入集合S;
//找出集合S中的x值大于x[i]的最小元素j;
if m[j]=m[i] then //将状态j从S中删去;
}
}
从性质D和算法描述可以发现,S实际上是以x值为关键字(也是以m值为关键字)的有序集合。若使用平衡树实现有序集合S,则该算法的时间复杂度为O(n*log2n)。(每个状态转移的状态数仅为O(1),而每次状态转移的时间变为O(log2n))。
- 找出n个数组成的最长单调递增子序列( 动态规划O(nlogn) )
- 设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
- 最长递增子序列的求解(O(n*n),O(nlogn))——动态规划
- 单调递增最长子序列 O(nlogn)
- 最长单调递增子序列O(nlogn)
- 算法_动态规划_最长单调递增子序列问题(O(nlogn)的时间复杂度)
- 利用动态规划找出最长公共单调递增子序列
- ACM最长单调递增子序列问题(动态规划)o(n*n)C++实现
- ACM最长单调递增子序列问题(动态规划)o(n*n)C++实现
- 找出由n个数组成的序列内最长的递增子序列
- 最长单调递增子序列O(NlogN)算法
- 动态规划解最长递增子序列(O(n^2))
- 动态规划:最长单调递增子序列
- 动态规划--最长单调递增子序列
- 【动态规划】单调递增最长子序列
- 最长单调递增子序列--动态规划
- 最长递增子序列 O(n^2) 与 O(nlogn)
- 算法导论15.4-6 求一个n个数的序列的最长单调递增子序列 O(n*logn)
- sqlserver2008配置经历
- jTemplates使用心得
- 编程语言只是很小的一方面
- Intel8259A的初始化命令字
- 关掉和重启mysql进程
- 找出n个数组成的最长单调递增子序列( 动态规划O(nlogn) )
- KMP算法
- Drupal Views的帮助文档都有哪些?
- KMP字符串匹配
- HTTP学习总结-------1
- Android 在OnCreate()中获取控件高度与宽度
- ios 发送http协议请求消息
- Jquery动态增加行和删除行
- iOS应用的真机调试