最长递增/递减子序列

  • 题目如下:

    求一个数组的最长递减子序列

    比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}

    求一个数组的最长递增子序列

    比如{1,-1,2,-3,4,-5,6,-7}的最长递减子序列为{1,2,4,3,6}

    最长递增序列和最长递减子序列的解法是一样的,最不济,也可以先revert,求完再revert一次。

     

    首先我们得搞清一个范围问题,虽然我们要的是一个最大值,但是是不是他是可以递推的呢,就是我只保存一个最大值,然后不断增加这个值,直觉上看应该是不太现实的,比如:12345-101234,我们数到5时最大值是5,但往后看时,都比5小,不能增加最大值,但事实上是最大值是6,如果我们受限于前面求的的一个最大值,就会产生错误的结果,也许你可以说,我就是保存一个值,没到一个点我就重新算新的最大值,虽然牺牲一点计算,但是我就想只有一个变量,有思路吗?如果没有就换个思路吧。既然递推困难,我们就把各个备选值都列出来,然后找出那个最大的,那哪些是备选值呢?其实以任意元素为终点的递增序列都是合法的candidate。

     

    解法1:

    如同上面的分析,考虑一个序列x0, x1,x2,… xn-1, xn。我们想知道以每个元素为终点的最长递增子序列的长度,令temp[i]表示以xi为终点的递增序列的长度,假设已经知道了temp[0]-temp[n-1],那如何求temp[n]呢?如果xi<xn那,xi就有可能在xn为终点的序列上,那以xn为终点的递增序列就至少是xi的最长序列+1。下面是代码:

     

     

    #include <iostream>

    using namespace std;

     

    int LIS(int arr[],int n)

    {

        int *temp = new int[n];//存放当前遍历位置最长序列 

        for(int i=0;i<n;++i)

        {

            temp[i]=1;   //初始化默认长度 

            for(int j=0;j<i;++j) //找出前面最长的序列 

            {

                // 当前值 array[i] 跟已经遍历的值比较,

                //大于已经遍历的值且已知递增序列+1 大于当前值则 更新当前最长递增序列值 

                if(arr[i]>arr[j]  && temp[j]+1 > temp[i] )

                {

                    temp[i] = temp[j] + 1;

                }

                

            }

        }

        

        int max=temp[0];

        for(int k=0;k<n;++k)//找出整个数组中最长的子序列 

        {

            if(max<temp[k])

                max=temp[k];

        }

        

        return max;

        

    }

     

    int main()

    {

        int arr[]={1,-1,2,-3,4,-5,6,-7};

        int result=LIS(arr,8);

        cout<<result<<endl;

        

    }

     

    解法2:

    解法1中用一个数组存储以各个元素为终点的最长递增子序列的长度,然后每新增加一个元素时,就遍历前面所有的元素,来知道新元素的temp值,复杂度是O(n2)。每个元素都得求一遍,这是毋庸置疑的,求法上能不能优化一下呢?那就把前面元素和其最长递增序列值排个序吧,当求xn的最长递增序列时,找到前面的序列中比xn小的最大值(可能有多个,位置不同时,序列长度也会不一样),然后加一个1就可以了。

     

     

     

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中最长递增子序列的代码可以有多种实现方式。引用\[1\]中给出了一种实现方式,使用了动态规划的思想。该代码定义了一个函数`lis`,接受一个整数数组作为参数。它首先初始化一个长度为数组长度的列表`m`,用于记录以每个元素结尾的最长递增子序列的长度。然后通过两层循环遍历数组,如果当前元素比后面的元素小且以当前元素结尾的子序列长度小于等于以后面元素结尾的子序列长度,则更新以当前元素结尾的子序列长度。最后找到`m`列表中的最大值,然后遍历数组,将与最大值相等的元素添加到结果列表中,并递减最大值,直到最大值为0。最后返回结果列表。给定的示例数组为`\[10, 22, 9, 33, 21, 50, 41, 60, 80\]`,调用`lis`函数后输出结果为`\[10, 22, 33, 50, 60, 80\]`。 另外,引用\[2\]中给出了另一种实现方式,使用了动态规划和二分查找的思想。该代码定义了一个类`Solution`,其中包含一个方法`lengthOfLIS`,接受一个整数数组作为参数。它首先判断数组是否为空,如果为空则返回0。然后初始化一个长度为数组长度的列表`dp`,用于记录以每个元素结尾的最长递增子序列的长度。通过两层循环遍历数组,如果当前元素比前面的元素大,则更新以当前元素结尾的子序列长度为前面元素结尾的子序列长度加1。最后返回`dp`列表中的最大值。这种实现方式的时间复杂度为O(n)。 #### 引用[.reference_title] - *1* [Python 最长递增子序列代码](https://blog.csdn.net/deanhj/article/details/101634446)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [最长连续序列 python](https://blog.csdn.net/dearzhuiyi/article/details/126930325)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值