求最长上升子序列

来源:互联网 发布:美工设计学习 编辑:程序博客网 时间:2024/06/18 12:56

求最长上升子序列

笔者在湖大参加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

实现代码

//javaclass 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 0
原创粉丝点击