最长递增子序列(输出最长递增序列 及其长度)

最长递增子序列的解法有很多种,常用的有最长公共子序列法、动态规划、记录所有递增序列长度最大值的方法。

最长公共子序列法:如例子中的数组A{5,6, 7, 1, 2, 8},则我们排序该数组得到数组A‘{1, 2, 5, 6, 7, 8},然后找出数组A和A’的最长公共子序列即可。显然这里最长公共子序列为{5, 6, 7, 8},也就是原数组A最长递增子序列。

在http://blog.csdn.net/yysdsyl/article/details/4226630中有详细解释。

动态规划:参见http://qiemengdao.iteye.com/blog/1660229

这里主要介绍第三种方法:时间复杂度O(n lgn)

维护一个数组MaxV[i],记录所有长度为i的递增子序列中最大元素的最小值。
思路:遍历数组,如果数组中该元素a[k]大于MaxV[len-1]的值,直接len++,MaxV[len]=a[k];

   否则从MaxV中从后向前,找到第一个比a[k]大的值的索引j,并将MaxV[j]更新为a[k](即长度为j的递增序列最大值的最小值应为a[k]),查找过程可以使用二分搜索。

  为了记录最大递增序列,我们使用maxIndex记录其索引,注意需要初始化maxIndex[0]=0;在a[k]>MaxV[len-1] 和 a[k]<MaxV[len-1]&&pos==len-1时,都需要更新maxIndex的值。

所以博客http://blog.csdn.net/imzoer/article/details/8100064的解法是有问题的,这里已经更正。

 1 //修改后的二分搜索,返回从后向前,第一个比target大的索引
 2 int bsearch(int *a, int s, int e,int target)
 3 {
 4     while(s<=e)
 5     {
 6         int mid = s +(e-s)/2;
 7         if(a[mid]<=target)
 8         {
 9             s=mid+1;
10         }
11         else
12         {
13             e = mid-1;
14         }
15     }
16     return s;
17 }
18 int getMaxSub(int *a, int n)
19 {
20     int *maxIndex = new int[n];
21     int *maxV = new int[n];
22     int len =1;
23     maxV[0] = a[0];
24     maxIndex[0]=0;
25     for(int i=1; i <n; i++)
26     {
27         if(a[i]>maxV[len-1])
28         {
29             maxV[len]=a[i];
30             maxIndex[len]=i;
31             len++;
32         }
33         else
34         {
35             int pos = bsearch(a,0,len-1,a[i]);
36             maxV[pos]= a[i];
37             if(pos == len-1)
38                 maxIndex[pos]=i;
39         }
40     }
41     for(int i=0;i<len;i++)
42     {
43         printf("%d\t",a[maxIndex[i]]);
44     }
45     printf("\n");
46     return len;
47 }
48 int main()
49 {
50
51
52     int a[]={
53         7,5,4,2,3,5,6,1,5,8,9,10
54     };
55     int b[]={
56         1, 5, 8, 3, 6, 7, 2, 9
57     };
58     printf("The array is :\n");
59     for(int i=0;i<12;i++)
60     {
61         printf("%d\t",a[i]);
62     }
63     printf("\nThe max ascending array is:\n");
64     printf("The length of max ascending array is :%d\n",getMaxSub(a,12));
65     //getMaxSub(b,8);
66
67 }
时间: 2024-10-19 07:15:01

最长递增子序列(输出最长递增序列 及其长度)的相关文章

最长递增子序列 &amp;&amp; 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更好的方

最长公共子序列和最长递增子序列

1.最长公共子序列:(x和y是两个数组的长度) f(x,y) = 0                               if(x==0 || y==0) f(x-1,y-1)+1               if(A[x-1]==B[y-1]) max{f(x-1,y), f(x,y-1)} if(A[x-1]!=B[y-1]) 2.最长递增子序列 (1) 最长公共子序列法:排序后与原数组的最长公共子序列. (2) 动态规划法:(时间复杂度O(N^2)) 设长度为N的数组为{a0,a1

poj2250 最长上升子序列 + 输出

1 //Accepted 208 KB 0 ms 2 //最长公共上升子序列+输出 3 //dp 4 //输出时用的递归输出,注意条件判断 5 #include <cstdio> 6 #include <cstring> 7 #include <iostream> 8 using namespace std; 9 const int imax_n = 105; 10 const int imax_stringlen = 32; 11 char s1[imax_n][im

O(n log n)求最长上升子序列与最长不下降子序列

考虑dp(i)表示新上升子序列第i位数值的最小值.由于dp数组是单调的,所以对于每一个数,我们可以二分出它在dp数组中的位置,然后更新就可以了,最终的答案就是dp数组中第一个出现正无穷的位置. 代码非常简单: for(int i=0;i<n;i++)dp[i]=oo; for(int i=0;i<n;i++)*lower_bound(dp,dp+n,A[i])=A[i]; printf("%d\n",(lower_bound(dp,dp+n,oo)-dp)); 如果是最长不

最长上升子序列输出序列贪心做法

之前做过的最长上升子序列的题只是不需要输出这个序列http://www.cnblogs.com/Scale-the-heights/p/4333346.html 做法就是从左到右扫一遍,可以参见http://blog.csdn.net/shuangde800/article/details/7474903 要输出路径其实也很简单,就开个数组f[]把所有数字在最长上升子序列中第一次出现的位置记录下来,然后逆序遍历,比如我们找到最长上升子序列的长度为n,则我们从后往前找到曾经在最长上升子序列中位置为

最长公共子序列——输出

首先我不得不说这道题很傻逼....你要先求公共子序列的长度......然后去DFS一遍注意要倒着搜......公共子序列也要倒着找..........我做了好久,代码: #include<bits/stdc++.h> using namespace std; char a[1001],b[1001]; int dp[1001][1001]={0}; int n1,n2,sum=0; int ans[1001]={0}; int a1[1001][101],b1[1001][101]; int

最长递归子序列、最长公共字串、最长公共子序列、编辑距离

[TOC]   ### 最长递归子序列 #### 题目 给定数组arr,返回arr中的最长递增子序列,如`arr=[2,1,5,3,6,4,8,9,7]`,返回的最长递增子序列为`[1,3,4,8,9]` #### 题解思路 先用DP来求解子序列递增的最大长度,如arr的长度序列为`dp=[1,1,2,2,3,3,4,5,4]`,然后对这个长度序列dp从右到左遍历,得到最长递增子序列. 1. 求解长度序列,令dp[i]表示在以arr[i]这个数结尾的情况下,arr[0...i]中的最大递增子序列

最长上升子序列 和 最长不下降子序列

最长上升子序列:是严格上升的,a<b<c<d这样的,即为严格单调递增,用lower_bound lower_bound:返回序列中大于等于key值的第一个数 比如说序列 1 2 3 4 5,key值为3,使用lower_bound返回第三个数 最长不下降子序列:不是严格上升,可以存在多个数相等的情况,用upper_bound upper_bound:返回序列中严格大于key值的第一个数 比如说序列1 2 3 4 5,key值为3,使用upper_bound返回第四个数 Hdu 1950

最长公共子序列和最长公共子序列

最长公共子序列: 例如:abcfbc abfcb                答案是:4: 最长公共子串  :答案是: 2: 代码: 最长公共子序列: #include<cstdio> #include<cstring> #define max(x,y) (x>y?x:y) int len1,len2; int dp[1010][1010]; int bj[1010][1010]; char ch1[1010],ch2[1010]; void LCS() //lcs最长公共

最长公共子序列 与 最长公共连续子串

最长公共子序列 //最长公共子序列(个数) #include<iostream> using namespace std; int c[100][100]={0}; int len1,len2; int gcd(string a,string b){ len1=a.length(); len2=b.length(); int tmp=-1; for(int i=0;i<len1;i++) { for(int j=0;j<len2;j++){ if(a[i]==a[j]) c[i][