这题目是经典的DP题目,也可叫作LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列。很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) 。

利用LCS算法实现
思路:设原序列为A[],将A[]进行排序后生成排好序的序列B[],利用LCS 算法查找A[],B[]的最长公共子序列即可找出LIC。
时间复杂度:分为排序和LCS两块,最终为O(n^2)
代码可以参考前面的关于LCS的文章。

动态规划的思想

定义L(j)={ max(L(i))+1, i<j且a[i]<a[j] }。也就是说,我们需要遍历在j之前的所有位置i(从0到j-1),找出满足条件a[i]<a[j]的L(i),求出max(L(i))+1即为L(j)的值。最后,我们遍历所有的L(j)(从0到N-1),找出最大值即为最大递增子序列。时间复杂度为O(N^2)。
代码实现:

#include <iostream> #define SIZE 10000 #include <vector> #include <stdlib.h> using namespace std; //a[]为序列数组,d[t]记录0...t的LIS的最大长度,p[]记录前一个LIS的位置 void LIS(int *a,int length,int *d,int* p) {     int i,j;     d[0]=1;p[0]=-1;             //初始化,以a[0]结尾的最长递增子序列长度为1     for(i=1;i<length;i++)     {         d[i]=1;p[i]=-1;         //d[i]最小值为1         for(j=0;j<i;j++)             if(a[i]>a[j]&&d[j]+1>d[i])             {                 d[i]=d[j]+1;                 p[i]=j;            //记录位置             }     } } void printAnswer(int *d,int* p,int length) {     int i,j,max=0;     for(i=0;i<length;i++)     {         if(d[i]>max)         {             max=d[i];             j=i;         }     }     cout<<"Max length:"<<max<<endl;     while(p[j]!=-1)     {         cout<<p[j]<<"  ";         j=p[j];     } } int main() {     int i,a[SIZE],d[SIZE],p[SIZE],c[SIZE];     vector<int> vec;     for(i=0;i<SIZE;i++)     {         vec.push_back(i);     }     srand(10);     for(i=0;i<SIZE;i++)     {         vec.push_back(i);     }     for(i=0;i<SIZE;i++)     {         int index = rand() % vec.size();      vector<int>::iterator iter = vec.begin() + index;       a[i]=*iter;         vec.erase(iter);     }     cout<<"LIS:"<<SIZE<<"numbers!"<<endl;     LIS(a,SIZE,d,p);     printAnswer(d,p,SIZE);     return 0; }

运算结果:

O(nlgn)算法

目的:在前i个元素中的所有长度为len的递增子序列中找到这样一个序列,它的最大元素比arr[i+1]小,而且长度要尽量的长,如此,我们只需记录len长度的递增子序列中最大元素的最小值就能使得将来的递增子序列尽量地长。

方法:维护一个数组MaxV[i],记录长度为i的递增子序列中最大元素的最小值,并对于数组中的每个元素考察其是哪个子序列的最大元素,二分更新MaxV数组,最终i的值便是最长递增子序列的长度。

代码实现:

//在a[0]..a[len]中,找到最大的j,满足a[j] <= n int find(int *a,int len,int n) {     if(len==1) return 1;     int left=0,right=len-1,mid=(left+right)/2;     while(left<=right)     {         if(n>a[mid]) left=mid+1;         else if(n<a[mid]) right=mid-1;         else return mid;         mid=(left+right)/2;     }     return left; } void LIS2(int *a,int length,int *c,int *d,int* p) {     int i,j,len;     c[0]=0;//     c[1]=a[0];//     d[0]=1;     len=0;     for(i=0;i<SIZE;i++)     {         if(a[i]>c[len]) j=++len;         else j=find(c,len,a[i]);         c[j]=a[i];     }     cout<<"MaxLength"<<len<<endl; }
int main() {     int i,a[SIZE],d[SIZE],p[SIZE],c[SIZE];     vector<int> vec;     for(i=0;i<SIZE;i++)     {         vec.push_back(i);     }     srand(10);     for(i=0;i<SIZE;i++)     {         vec.push_back(i);     }     for(i=0;i<SIZE;i++)     {         int index = rand() % vec.size();        vector<int>::iterator iter = vec.begin() + index;       a[i]=*iter;         vec.erase(iter);     }     cout<<"LIS:"<<SIZE<<"numbers!"<<endl;     LIS2(a,SIZE,c,d,p);     return 0; } 

得到的结果与前面的算法相同,不过只能打印出LIS的大小,还没想到怎样去打印出序列。

转载于:https://blog.51cto.com/8672742/1368663

动态规划-最长上升子序列(LIS)相关推荐

  1. 最长上升子序列_动态规划 最长上升子序列LIS

    问题描述 最长上升子序列(LIS): 给定长度为n的序列,从中选中一个子序列,这个子序列需要单调递增,请问最长子序列(LIS)的长度? eg:1,5,2,3,11,7,9 则LIS序列为:1,2,3, ...

  2. 动态规划 - 最长递增子序列LIS

    问题:一个序列有N个数:A[1],A[2],-,A[N],求出最长非降子序列的长度 样例输入:3 1 2 6 5 4 思路: 首先把问题简单化.可以先求A[1],...A[i]的最长非降子序列,令dp ...

  3. 动态规划——最长上升子序列问题(LIS)

    动态规划--最长上升子序列问题(LIS) 最长上升子序列问题(LIS).给定n个整数A1,A2,-,AnA_1, A_2, \dots , A_n,按从左到右的顺序选出尽量多的整数,组成一个上升子序列 ...

  4. 最长上升子序列(LIS)长度

    转自:http://www.slyar.com/blog/poj-2533-cpp.html POJ 2533 Longest Ordered Subsequence 属于简单的经典的DP,求最长上升 ...

  5. 耐心排序之最长递增子序列(LIS)

    目录 一.问题引入 1.最长递增子序列(LIS) 2.问题分析 3.代码实现 4.问题思考 二.耐心排序 1.基本介绍 2.操作步骤 3.代码实现 三.俄罗斯套娃信封问题 1.题目描述 2.问题分析 ...

  6. 动态规划—最长公共子序列问题 HDU-1159 Common Subsequence

    动态规划-最长公共子序列问题 Common Subsequence [ HDU - 1159 ] A subsequence of a given sequence is the given sequ ...

  7. 详解动态规划最长公共子序列--JavaScript实现

    前面两篇我们讲解了01背包问题和最少硬币找零问题.这篇将介绍另一个经典的动态规划问题--最长公共子序列.如果没看过前两篇,可点击下面链接. 详解动态规划最少硬币找零问题--JavaScript实现 详 ...

  8. 动态规划1--最长公共子序列

    动态规划1--最长公共子序列 一.动态规划 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题.简单地采用把大问题分解成子问题,并 综合子问题的解导出大问题的解的方法,问题求解耗时 ...

  9. 最长上升子序列(LIS) nlogn解法

    文章目录 经典DP解法O(n^2) dp+二分法(O(nlogn)) 最长上升子序列LIS:Longest increasing subsequence 题目链接:Leetcode300. 最长递增子 ...

  10. 最长公共子序列php,动态规划(最长公共子序列LCS)

    概念 求解决策过程最优化的结果 (可能有多个) 把多阶段过程转化为一系列单阶段过程,利用各阶段之间的关系,逐个求解 计算过程中会把结果都记录下,最终结果在记录中找到. 举例 求两个字符串的最长公共子序 ...

最新文章

  1. 各个数据库取前10行记录
  2. 从windows server的文件服务到分布式文件服务(一)
  3. Pat甲级 1001 A+B Format
  4. mac book pro怎么安装python_Mac安装python细节
  5. 【数据挖掘】挖掘建模-回归分析(1)
  6. 皕杰报表和炎黄盈动(AWS BPM)集成 操作手册
  7. oppo 手机侧滑快捷菜单_[图]OPPO又出脑洞设计:弹出/侧滑第二块手机屏幕
  8. 如何将Android Studio项目提交(更新)到github
  9. Bootstrap学习之三:使用排版
  10. linux tomcat8+jdk1.8u201百度云盘下载
  11. <数据结构> 顺序表
  12. 如何成为一名优秀的程序员
  13. 纯前端实现—用户注册登录界面
  14. 华为P40与周冬雨排列
  15. 浅析网站被挂马的代码
  16. Axure8有效注册码
  17. 微信小程序Excel生成下载浏览分享
  18. linux利用源码安装madplay
  19. 前端-Vuejs2.5开发去哪儿网
  20. 数字U家,即刻出发,2022联合利华黑客马拉松启动

热门文章

  1. Qt5.6.0+OpenGL 纹理贴图首战告捷
  2. The easy way to implement a Red-Black tree
  3. java 读excel
  4. 工作站的windows server 2008 终于安装好了
  5. HAproxy开启日志记录
  6. Springboot实现邮件发送(2020最新版)
  7. Struts2之HttpServletRequest、HttpServletResponse,HttpSession,Parameters处理
  8. linux 如何解压.exe,linux下解压火狐浏览器压缩包 ./filefox 运行可执行程序报错问题...
  9. 避坑:一次离奇性能故障的排查与反思
  10. L2-007. 家庭房产