题目链接https://www.acwing.com/problem/content/897/
一、求最长上升子序列长度
这个题其实还是跟之前一样的思路,f[i]
可以看作以num[i]
为末尾的最长子序列的长度集合,现在要求集合中的最大值。f[i]
可以用f[j]+1
来表示,此处j
是这个上升子序列的倒数第二个值,用循环来求
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] num = new int[1005];
int[] f = new int[1005];
for(int i = 1; i <= n; i++) num[i] = in.nextInt();
for(int i = 1; i <= n; i++) {
f[i] = 1;
for(int j = 1; j <= n; j++) {
if(num[i] > num[j]) {
f[i] = Math.max(f[i],f[j] + 1);
}
}
}
int res = 0;
for(int i = 1; i<= n;i++) {
res = Math.max(f[i],res);
}
System.out.print(res);
}
}
二、打印最长上升子序列(倒序输出)
打印最长子序列的时候可以用g[i]
数组来表示每个以num[i]
结尾的最长上升子序列的上一个数在num
数组中的下标。
以输入样例为例
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
num | 3 | 1 | 2 | 1 | 8 | 5 | 6 | |
f | 1 | 1 | 2 | 1 | 3 | 3 | 4 | |
g | 0 | 0 | 2 | 0 | 3 | 3 | 6 |
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] num = new int[1005];
int[] f = new int[1005];
int[] g = new int[1005];
for(int i = 1; i <= n; i++) num[i] = in.nextInt();
for(int i = 1; i <= n; i++) {
f[i] = 1;
g[i] = 0;
for(int j = 1; j < i; j++) {
if(num[i] > num[j]) {
if(f[i] < f[j] + 1){
f[i] = f[j] + 1;
// g[i]存的是以i结尾的序列的倒数第二个数在num中的下标
g[i] = j;
}
}
}
}
// 这个循环取出最大值
int k = 1;
for(int i = 1; i<= n;i++) {
if (f[k] < f[i]) k = i;
}
System.out.println(f[k]);
// 这个循环取出路径,输出为倒序
for (int i = 0, len = f[k]; i < len; i++) {
System.out.print(num[k]+" ");
k = g[k];
}
}
}