求最长上升子序列

求最长上升子序列

笔者在湖大参加WPS笔试时曾碰这么一道问题,当时没有想出好的办法,回学校后赶紧查了资料,现在我用自己的语言描述一下。

问题描述

一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序列(ai1, ai2, …, aiK),这里1 <= i1 < i2 < … < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

输入:任意长度的数组

输出:该数组中最长子序列的长度

案例:

输入:[1, 7, 3, 5, 9, 4, 8]

输出:[1, 3, 5, 8]

解题思路

有经验的同学一定可以看出来,这就是一道动态规划的题目,那么我们就只需要找出它的子问题。这道题的子问题我们可以设为“求以ak(k=1, 2, 3…N)为终点的最长上升子序列的长度“,注意,这里的子问题我们不是设为”求到ak(k=1, 2, 3…N)为止的a1,a2…ak之间数组的最长上升子序列的长度“。

转移方程也就随之而出了

①MaxLen (1) = 1 //这里的MaxLen(n)表示以数组下标n为终点的最长上升子序列的长度

②MaxLen (k) = Max { MaxLen (i):1< i< k 且 ai < ak且 k≠1 } + 1

当然,②也有另一种表述MaxLen (k) = Max { MaxLen (i)+1:1< i < k 且 ai < ak且 k≠1 },本质上是一样的。使用转移方程之前,要初始化 MaxLen(n) = 1

实现代码

//java
class MaxSubLenTool{
public static int getMaxSubLen(int[]nums){
    if(nums == null || nums.length <= 0)
        return -1;
    if(nums.length == 1)
        return 1;
    int seqlen[] = new int[nums.length];//对应下标所在数字为升序终点的最大长度
    for(int i = 0 ;i < nums.length ;i ++)
        seqlen[i] = 1;
    int maxLen = 1;
    for(int i = 1 ; i < nums.length ; i ++){
        for(int j = i-1 ; j >= 0; j --){
            if(nums[j] < nums[i] && seqlen[j]+1 > seqlen[i]){
                System.out.println("nums[j] = "+nums[j]+",nums[i] = "+nums[i]);
                seqlen[i] = seqlen[j] + 1;
            }
        }
        if(seqlen[i] > maxLen)
            maxLen = seqlen[i];
    }
    for(int key:seqlen)
        System.out.println(key);
    System.out.println("res");
    return maxLen;
}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值