最长子序列 (经典动态规划题)
来源:互联网 发布:3d场景软件 编辑:程序博客网 时间:2024/05/20 14:19
原文地址:http://blog.163.com/kevinlee_2010/blog/static/169820820201092091343405/
例如:有一个序列,例如 9 8 2 1 7 5 3 4 3 2 1.
求出最长的递减子序列。如本例的结果就是:9 8 7 5 4 3 2 1。
算法:
此题为动态规划经典题目,时间复杂度O(n^2)。
解法如下:
设原数组为a[1....n]。设一数组d[1....n],其中d[i]表示从第i个元素开始(一定
包含第i个元素),到整个数组末尾的子序列 a[i...n]中的最长递减子序列的长度。
则本问题就是要在求出d[1]的同时,恢复出最优解。
下面给出递推式:
d[i]的值分两种情况:
1、当i=n时,d[i]=1。即最后一个元素的序列的最大递减子序列中只有它自己。
2、当i<n时,d[i]=max{d[k]| i<k<=n 且a[i]>a[k]} +1。解释意思为,包含第i个
元素的序列a[i...n]的最大子序列依赖于i后面所有的序列中比a[i]小(满足递减
特性),且最大的d[k](满足最 优特性)值再加1(加上a[i]元素)。在给d[i]赋
值的时候只需记录p[i]=k,既可以作为parent属性恢复出解。
具体实现的话,开两个数组d[n],p[n],外层循环从后往前选取i,内层循环从i往
后寻找最优的k,双循环遍历即可求出所有的d[i]。然后 再进行一次O(n)操作,找
出最大的d[max]。恢复解的话,可以从p[max]开始,依次恢复出各个解。
C++代码:
//求一个数组的最长递减子序列
void longest_decrease_sub(int *a, int size){
int *d=new int[size]();
int *p=new int[size]();
d[size-1]=1;
for(int i=size-1;i>=0;i--){
int max=0;
int index=0;
for(int j=i;j<size;j++){
if(a[i]>a[j] && max <d[j]){
max=d[j];
index=j;
}
}
if(max==0){
d[i]=1;
p[i]=-1;
}else{
d[i]=max+1;
p[i]=index;
}
}
//寻找最大子序列的起始下标
int max=0;
int max_index=0;
for(int i=0;i<size;i++){
if(d[i]>max){
max=d[i];
max_index=i;
}
}
//从最大子序列的下标开始 输出子序列
cout<<"\n最长递减子序列的长度为:"<<d[max_index]<<",最长子序列为:"<<ends;
for(int i=max_index;i!=-1;i=p[i]){
cout<<a[i]<<" "<<ends;
}
delete [] d;
delete [] p;
}
欢迎大家测试~
- 最长子序列 (经典动态规划题)
- 单调递增最长子序列 (动态规划经典题)
- 最长公共子序列(经典的动态规划)
- 动态规划经典问题---最长公共子序列(LCS)
- nyist oj 17 单调递增最长子序列 (动态规划经典题)
- nyist oj 17 单调递增最长子序列 (动态规划经典题)
- 编辑距离和最长公共子序列(动态规划经典题)
- NYOJ题目36-最长公共子序列(经典动态规划题)
- nyist oj 17 单调递增最长子序列 (动态规划经典题)
- 最长递增子序列(动态规划)
- 最长公共子序列(动态规划)
- 最长公共子序列(动态规划)
- 最长递增子序列(动态规划)
- 动态规划(最长子序列)
- 最长公共子序列(动态规划)
- 最长公共子序列(动态规划)
- 最长公共子序列(动态规划)
- 最长公共子序列(动态规划)
- 键盘 Key Code对照表
- 计算机知识准备
- Rest API Reference
- 献给java初学者
- 开始我的C++
- 最长子序列 (经典动态规划题)
- Android导入自定义的jar包时出现 E/AndroidRuntime(486): java.lang.NoClassDefFoundError错误
- 前端开发 调试工具 Chrome Workspace
- 顺序表+单链表+双链表
- 一个有趣的面试题
- 如何在技术面试中脱颖而出(上)
- POJ —— 二分
- WMI技术介绍和应用——查询正在运行的进程信息
- 博客开通