《动态规划_入门 LIS 问题 》
问题描述
问题 A: 最长上升子序列
时间限制: 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 }