免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8956 | 回复: 11
打印 上一主题 下一主题

最长递减子序列 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-05-09 13:55 |只看该作者 |倒序浏览
设有一个整数序列A1, A2, ... An,求这个序列中最长的递减子序列的长度M, 以及该序列可以划分成这种子序列的个数N
如序列:
300 250 252 275 200 138 245
折分成的子序列分别为
300 275 200 138
252 245
250
其中最长序列为:
300 275 200 138
所以M=4, N=3

论坛徽章:
0
2 [报告]
发表于 2006-05-09 14:10 |只看该作者
我得到的结果是扫描一遍序列,可以得到最长子序列,要拆分所有的子序列,最差的情况下(序列递增)要拆n次,所以是个O(n*n)的

论坛徽章:
0
3 [报告]
发表于 2006-05-09 18:43 |只看该作者
原帖由 yzc2002 于 2006-5-9 13:55 发表
设有一个整数序列A1, A2, ... An,求这个序列中最长的递减子序列的长度M, 以及该序列可以划分成这种子序列的个数N
如序列:
300 250 252 275 200 138 245
折分成的子序列分别为
300 275 200 138
252 245
2 ...


没看懂题目。 300 250 为什么不算递减的? 300 自己作为一个序列呢?

论坛徽章:
0
4 [报告]
发表于 2006-05-10 09:04 |只看该作者
要求得到的递减子序列是最长的
举的例子不是很好,因为有很多个相同长度的递减子序列,长度都为4
再看序列
300 250 275 252 200 138 245
这个的最长子序列是
300 275 252 200 138
长度为5

[ 本帖最后由 yzc2002 于 2006-5-10 09:07 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2006-05-10 09:11 |只看该作者
递归实现吧
给一个例子,我只计算了最长子序列的长度

  1. #include <iostream>
  2. using namespace std;

  3. int MaxSubseq_Recur(int nums[], int count, int max);

  4. int main(){
  5.         int nums[]={300, 250, 275, 252, 200, 138, 245};
  6.         int count=sizeof(nums)/sizeof(int);
  7.        
  8.         cout<<"The result of sequence {";
  9.         for (int i=0; i<count-1; ++i)
  10.                 cout<<nums[i]<<',';
  11.         cout<<nums[count-1]<<"} is "<<MaxSubseq_Recur(nums, count, 350)<<endl;
  12.        
  13.         return 0;
  14. }
  15.        
  16. int MaxSubseq_Recur(int nums[], int count, int max) {
  17.         //在序列(nums[], count)中寻找比最长子序列,其中序列中的数应比max都小
  18.         int tmp1, tmp2;

  19.         if(count==1)
  20.                 return nums[0]<max?1:0;
  21.         else {
  22.                 if(nums[0]<max) { //nums[0]可选
  23.                         tmp1=MaxSubseq_Recur(nums+1, count-1, nums[0])+1;        //选
  24.                         tmp2=MaxSubseq_Recur(nums+1, count-1, max);                        //不选
  25.                         return tmp1>tmp2?tmp1:tmp2;
  26.                 }
  27.                 else
  28.                         return MaxSubseq_Recur(nums+1, count-1, max);
  29.         }
  30. }       
复制代码


望大家多多指教!

[ 本帖最后由 tyc611 于 2006-5-10 10:22 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-05-10 10:24 |只看该作者
还有,LZ的第二需求理解不了

论坛徽章:
0
7 [报告]
发表于 2006-05-10 14:38 |只看该作者
tyc611的算法是O(2^n)的,当串的长度增大时,速度会变得很慢
如取32个数的递减序列
100, 99, 98, ..., 69
试验一下就可以看出
最小个数N是指一个串能最少分割成递减序列的个数

论坛徽章:
0
8 [报告]
发表于 2006-05-10 14:41 |只看该作者
以 300 250 252 275 200 138 245 为例,300 起点的最长递减子串可以归结为 比 300 小的元素起点的最长递减子串

于是有模式 f (300) = max {f(250), f(252) ....} + 1

这个跟 FB 序列有点类似,倒过来做会比较方便

300  250  252  275  200  138  245
                                          1
                                    1
                            2
                     3                           
               3
        3
4


其中每一步可以记下当前最大串数量,若要输出最大串,则可以记录转向标记,比如 200 的  next 为 138, 275 的 next 为 200,  300 的 next 为 250, 252, 257 (想法而已,大概可以实现)。

每一步都要搜索其后较小的数,若数据量比较大,可以采用辅助结构,如二叉树之类的。

[ 本帖最后由 win_hate 于 2006-5-10 14:43 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2006-05-10 14:51 |只看该作者
再来一个例子

5 100 99 4 32 1
3  4   3   2 2  1
1  2   2   1 1  1

最长串长度为 4,有2个。

第二行是长度,第三行是数量

[ 本帖最后由 win_hate 于 2006-5-10 14:59 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2006-05-10 15:35 |只看该作者
前面给出的算法不好,没必要从尾开始搜索。改 ``以 xx 起点的串‘’ 为 ``以 xx 结尾的串'' 则可以从头开始处理。

例子

300 250 275 252 200 128 245

1     2    2     3     4     5    4
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP