问题:
Given an array of N integer,findthelengthofthelongestincreasingsubsequence。
For example,given [1,- 5,4,5,10,-1,- 5,7 ],thelongestincreasingsubsequenceislength4. (1,4,510 )
想法:
1、枚举
枚举数组的所有子序列,并确定它们是否为递增的子序列(回溯法)。
2、转化
对数组进行排序,找到新数组和旧数组的最长公用子序列LCS。
(有关最长公共子序列,请参见http://www.cn blogs.com/Andy JEE/p/4469196.html ) ) ) ) ) ) )。
3、动态规划
假设数组为a,则len[i]表示以第I个元素结束的最长递增子序列的长度,即第I个元素最大。
要获得len[i],可以获得以前面的i-1个元素结尾的最长增量数组。 如果A[i]小于前面A[0.i-1]中的某个元素k,则可以在相应的len[k]中加上1。 当然,最大的len[k];
有关详细信息,请参阅http://blog.csdn.net/ken by/article/details/6804720
4、优化
在上述方法中,在求出len[i]时,发现从a[1]、 a[i-1]到小于a[i]的所有元素,但a[1]、 a[i-1]无序,寻找速度慢。
提取数组f[k]表示长度为k的递增部分序列的末尾的元素,长度越长的序列其末尾的元素也越大,因此f[k]递增。
实例1、3、4、2和7
len[1]=1,f[1]=a[1]=1
len[2]=2,f[2]=a[2]=3
len[3]=3,f[3]=a[3]=4
len[4]=2,f [2]=a [4]=2(更新f [2] ) ) ) )
那么,怎么求len[5]?
f[1]=1,f[2]=2,f[3]=4,a[5]=7,
找到末尾元素小于a[5]且长度最长的递增子序列。 在本例中,
f[3]=4表示长度为3的子序列,末尾元素为4,此子序列的长度最长。
a[5]加上这个数组得到的新数组的长度为4,然后更新f[4]=a[5]=7,表示长度为4的子数组,其最后一个元素等于7
在上面的步骤中,找到末尾元素小于a[i]且长度最长的子列。 其实,关于f[1], f[k],我会从后向前找。 小于a[i]的第一个元素是长度最长的子列。 找的时候可以两点找方法,所以更快。
代码:
1、动态规划
#包含
#包含
用户命名空间STD;
unsignedintliss (常数交错[ ],size_t length,vector result ) )。
{
无符号int liss [ length ];
未指定int pre [ length ];
for(intI=0; I
liss[i]=1;
pre[i]=i;
}
int k=0;
int max=1;
for(intI=1; I
for(intj=0; Jj
if(Array[j]liss[I] ) {
liss[i]=liss[j] 1;
pre[i]=j;
最大值
max=liss[i];
k=i;
}
}
}
}
//i=max - 1;
wile(pre[k]!=k ()
//result[i--]=array[k];
result.push_back(Array[k];
k=pre[k];
}
//result[i]=array[k];
result.push_back(Array[k];
返回最大值;
}
int main () )
{
int A[]={1,- 5,4,5,10,-1,- 5,7 };
intlen=sizeof(a )/sizeof ) a[0];
向量结果;
coutliss(a,len,result ) endl;
for(intI=0; I
出局了
出局了
}
2、优化
#包含
#包含
用户命名空间STD;
unsignedintliss (常数交错[ ],size_t length,vector result ) )。
{
无符号int liss [ length ];
未指定int pre [ length ];
未指定int f [ length ];
for(intI=0; I
liss[i]=1;
pre[i]=i;
f[i]=0;
}
int k=0;
int max=1;
f[max]=0;
for(intI=1; I
for(intj=max; j=1; -j({
if(Array[f[j]]
liss[i]=j 1;
pre[i]=f[j];
if(f[liss[I]!=0}{
int old=array[f[liss[i]]];
if(Array[I]
f[liss[i]]=i;
}
else
f[liss[i]]=i;
最大值
max=liss[i];
k=i;
}
布雷克;
}
}
}
//i=max - 1;
wile(pre[k]!=k ()
//result[i--]=array[k];
result.push_back(Array[k];
k=pre[k];
}
//result[i]=array[k];
result.push_back(Array[k];
返回最大值;
}
int main () )
{
inta [ ]={ 1,3,4,2,7 };
intlen=sizeof(a )/sizeof ) a[0];
向量结果;
coutliss(a,len,result ) endl;
for(intI=0; I
出局了
出局了
}
OJ:在线测试
33558 www.now coder.com/question terminal/585 d 46 a 1447 b 4064 b 749 f 08 c2ab9ce 66
交流电源线:
类访问顺序{
公共:
intfindlongest (向量,int n ) {
向量DP (n;
向量(n;
dp[0]=1;
f[0]=A[0];
int left,right,mid;
int count=0;
int lmax=1;
for(intI=1; I
left=0;
right=count;
wile(left=right ) {
mid=left () right-left ) 1;
if(a ) I )=f(mid ) )
left=mid 1;
else
right=mid-1;
}
f[left]=A[i];
是左计数(if )
count=left;
dp[i]=left 1;
if(lmax )
lmax=dp[i];
}
返回最大值;
}
(;
类访问顺序{
公共:
intfindlongest (向量,int n ) {
int len=A.size (;
if(len=1) )。
返回len;
向量mlen (n,1 );
int lMax=1;
for(intI=1; I
for(intj=0; Jj
if(a(I ) a (j ) mlen )1mlen ) )
mLen[i]=mLen[j] 1;
if(mlen[I]lmax ) )。
lMax=mLen[i];
}
}
返回最大值;
}
(;