杭电oj1025-最长递增子序列

本文详细分析了求解最长递增子序列(LIS)问题的几种算法,包括将其转化为LCS问题、动态规划法及其优化。通过对算法的分析和代码实现,探讨了如何通过动态规划和二分查找降低时间复杂度,以解决杭电在线判题系统中的题目。最后展示了不同算法的优缺点,强调了算法设计与分析的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【最长递增子序列】
   
给定数列A1,A2,...An,求最长递增子序列
输入:
    第一行一个整数n,表示有n个数(n<=1000)
    第二行n个整数,用空格隔开。
输出:
    最长递增子序列长度。

【分析】
     在求以Ai为末元素的最长递增子序列时,找到所有序号在Ai前面且小于Ai的元素Aj,即j<i且Aj<Ai。如果这样的元素存在,那么对所有Aj,都有一个以Aj为末元素的最长递增子序列的长度S(j),把其中最大的S(j)选出来,那么S(i)就等于最大的S(j)加上1,即以Ai为末元素的最长递增子序列,等于以使S(j)最大的那个Aj为末元素的递增子序列最末再加上Ai;如果这样的元素不存在,那么Ai自身构成一个长度为1的以Ai为末元素的递增子序列。
    阶段i:以第i个数为末元素
    状态S[i]:以第i个数为末元素的可能递增序列长度
    转移方程:S[i+1]←max{S[i]}+1
【算法】
    S[1]:=1;                   {以第一个元素为末元素的递增序列长度肯定是1}
    For i←2 to n do
      For j←1 to i-1 do
        Begin
          搜索A[i]前面比A[i]小的数A[j],得到对应的S[j];
          S[i]←max{S[j]}+1;
        End;
    Write(max{S[i]});


【参考程序】

#include<stdio.h>

int main()

{

    

     intd[10],s[10];

     intlen,i,j,w;

     while(scanf("%d",&len),len)

     {

          for(i=0;i<len;i++)scanf("%d",d+i);

          s[0]=1;

          for(i=1;i<len;i++)//s[0...len-1]

          {

               w=0;

               for(j=0;j<i;j++)if(d[j]<d[i])

               {

                    if(s[j]>w)    w=s[j];

               }

               s[i]=w+1;

          }

          w=0;

          for(i=0;i<len;i++)if(s[i]>w)w=s[i];

          printf("%d\n",w);

     }

     return0;

}

最长递增子序列问题的不同求解方法求解

最长递增子序列问题是一个很基本、较常见的小问题,但这个问题的求解方法却并不那么显而易见,需要较深入的思考和较好的算法素养才能得出良好的算法。由于这个问题能运用学过的基本的算法分析和设计的方法与思想,能够锻炼设计较复杂算法的思维,我对这个问题进行了较深入的分析思考,得出了几种复杂度不同算法,并给出了分析和证明。

一,   最长递增子序列问题的描述

设L=<a1,a2,,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,,akm>,其中k1<k2<<kmaK1<ak2<<akm。求最大的m值。

二,   第一种算法:转化为LCS问题求解

设序列X=<b1,b2,,bn>是对序列L=<a1,a2,,an>按递增排好序的序列。那么显然X与L的最长公共子序列即为L的最长递增子序列。这样就把求最长递增子序列的问题转化为求最长公共子序列问题LCS了。


最长公共子序列问题用动态规划的算法可解。设Li=< a1,a2,,ai>,Xj=<b1,b2,,bj>,它们分别为L和X的子序列。令C[i,j]为Li与Xj的最长公共子序列的长度。则有如下的递推方程:

这可以用时间复杂度为O(n2)的算法求解,由于这个算法上课时讲过,所以具体代码在此略去。求最长递增子序列的算法时间复杂度由排序所用的O(nlogn)的时间加上求LCS的O(n2)的时间,算法的最坏时间复杂度为O(nlogn)+O(n2)=O(n2)

三,   第二种算法:动态规划法


设f(i)表示L中以ai为末元素的最长递增子序列的长度。则有如下的递推方程:

这个递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<iaj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。

这个算法由Java实现的代码如下:

public void lis(float[] L)

  {

         intn = L.length;

         int[]f = new int[n];//用于存放f(i)值;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大音若希

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值