问题描述
时间限制: 2 Sec 内存限制: 64 MB
提交: 461 解决: 236
一个数列ai如果满足条件a1 < a2 < ... < aN,那么它是一个有序的上升数列。我们取数列(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)。
现在你要写一个程序,从给出的数列中找到它的最长上升子序列。
输入包含两行,第一行只有一个整数N(1 <= N <= 1000),表示数列的长度。
第二行有N个自然数ai,0 <= ai <= 10000,两个数之间用空格隔开。
输出只有一行,包含一个整数,表示最长上升子序列的长度。
7
1 7 3 5 9 4 8
4
解题思路:
思路:
1.定义长度为n的dp数组,dp[i]表示为arr[i]结尾的最长递增子序列的长度。
2.对于第一个数arr[0]来说dp[0]=1,依次求出以i结尾的最长递增子序列
3.对于dp[i],求arr[i]结尾的最长递增子序列,在arr[0..i-1]中选出比arr[i]小且长度最长的
dp[j] , dp[i] = Math.max( dp[0…i-1] , dp[i] );如果所有的 dp[0…i-1] 都比 dp[i] 大,则 dp[i]=1;
所有的结果求出来后 遍历 dp数组,从dp数组中查找到最大的数值:
Java 实现代码
1 import java.util.Scanner;
2
3 public class Main {
4
5 public static int longestIncreasingSubsequence(int array[]) {
6 // 判断数组是否为空,或者长度是否为 0
7 if (array.length == 0 || array == null) {
8 return 0;
9 }
10 int len = array.length;
11
12 // 新申请一个数组,用来存放第 i 个位置的 最长公共子串是多少
13 int[] dp = new int[len];
14 // 最少能保证 第一个长度为1
15 dp[0] = 1;
16
17 for (int i = 1; i < len; i++) {
18 dp[i] = 1;
19 for (int j = 0; j < i; j++) {
20
21 if (array[i] > array[j]) {
22 dp[i] = Math.max(dp[i], dp[j] + 1);
23 }
24 }
25
26 }
27
28 int longest = Integer.MIN_VALUE;
29
30 for (int i = 0; i < array.length; i++) {
31 longest = Math.max(dp[i], longest);
32 }
33 return longest;
34 }
35
36 public static void main(String[] args) {
37 Scanner cin = new Scanner(System.in);
38 while (cin.hasNext()) {
39 int n = cin.nextInt();
40 int array[] = new int[n];
41
42 for (int i = 0; i < n; i++) {
43 array[i] = cin.nextInt();
44 }
45
46 int result = longestIncreasingSubsequence(array);
47 System.out.println(result);
48 }
49 }
50
51 }