最长不下降子序列java代码_浅谈最长不下降子序列与最长上升子序列

唔,最长不下降子序列与最长上升子序列曾是困扰蒟蒻多时的一个问题,应该也有一些人分不清这2个的求法吧。

首先n^2算法肯定是都能分清的,因为不下降和上升的区别是连续的2个能不能相等,只需要在判断的时候判一下是不是相等就可以了。

最长不下降子序列代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include

2 #include

3 using namespacestd;4 intn;5 int a[1100];6 int f[1100];7 intmain()8 {9 scanf("%d",&n);10 for(int i=1;i<=n;++i)scanf("%d",&a[i]);11 for(int i=1;i<=n;++i)12 {13 f[i]=1;14 for(int j=1;j=a[j]&&f[j]+1>f[i])f[i]=f[j]+1;16 }17 int ans=0;18 for(int i=1;i<=n;++i)19 ans=max(ans,f[i]);20 printf("%d",ans);21 return 0;22 }

View Code

最长上升子序列代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include

2 #include

3 using namespacestd;4 intn;5 int a[1100];6 int f[1100];7 intmain()8 {9 scanf("%d",&n);10 for(int i=1;i<=n;++i)scanf("%d",&a[i]);11 for(int i=1;i<=n;++i)12 {13 f[i]=1;14 for(int j=1;ja[j]&&f[j]+1>f[i])f[i]=f[j]+1;16 }17 int ans=0;18 for(int i=1;i<=n;++i)19 ans=max(ans,f[i]);20 printf("%d",ans);21 return 0;22 }

View Code

233333,如果不仔细看你会以为这2份代码是一样的,仔细看你会发现相似度99%。

但是窝分不清 的当然不是n^2的求法,而是nlogn的求法,之所以分不清,还是因为窝太弱了,窝用的二分从来都是stl,所以会经常搞混该用lower_bound还是upper_bound qwq

先来说一下nlogn的求解思想,令f[i]代表长度为i的所有最长不下降子序列的最后一位的最小值是多少。为什么要记录最小是多少那?因为我们想要这个序列最长,那么只有末尾最小才能有更多的数接到它的后面构成一个更长的序列。这时我们就能得到一个性质:f数组是递增的。证明:f[i]代表的是长度为i的最长不下降子序列的结尾最小的数,如果它后面来了一个比它大的数,那么这个数一定能构成至少长度为i+1的最长不下降子序列,所以在f数组里一定不会比它的位置靠前。

所以开一个变量len来记当前找到的最长不下降子序列有多长了,如果a[i]>=f[len],那么直接放到f[len]后面,并且len++,但是如果a[i]

有一个值得说明的点是f数组只是用来记录结尾的数的,f数组连起来并不是一个最长不下降子序列

最长上升子序列也是一样的道理,只不过由于要求严格递增,所以要替换的是大于等于它的第一个数

唔,二分用的2个stl分别是lower_bound和upper_bound,第一个是求大于等于一个数的第一个数的位置,第二个是求大于一个数的第一个数的位置。

最长上升子序列nlogn算法:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include

2 #include

3 #include

4 using namespacestd;5 intn;6 int a[100005],f[100005];7 intmain()8 {9 scanf("%d",&n);10 for(int i=1;i<=n;++i)scanf("%d",&a[i]);11 f[1]=a[1];int len=1;12 for(int i=2;i<=n;++i)13 {14 if(a[i]>f[len])f[++len]=a[i];15 else{16 int tmp=lower_bound(f+1,f+len+1,a[i])-f;17 f[tmp]=a[i];18 }19 }20 cout<

View Code

最长不下降子序列nlogn算法:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include

2 #include

3 #include

4 using namespacestd;5 intn;6 int a[100005],f[100005];7 intmain()8 {9 scanf("%d",&n);10 for(int i=1;i<=n;++i)scanf("%d",&a[i]);11 f[1]=a[1];int len=1;12 for(int i=2;i<=n;++i)13 {14 if(a[i]>=f[len])f[++len]=a[i];15 else{16 int tmp=upper_bound(f+1,f+len+1,a[i])-f;17 f[tmp]=a[i];18 }19 }20 cout<

View Code

其实相似度也是99%,233333333


版权声明:本文为weixin_39958366原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。