思想
1、穷举
容易想到,穷举所有可能,1 7 9,1 7 8,1 3 5 9 ,1 3 5 8…
2、动态规划实现
(1)一个数组存储输入数据——aa
(2)一个数据保存到第i位为止,的最大长度——bb
(3)初始bb[1] = 1,因为只有一个数,它本身的长度位1
(4)bb数组第二位,bb[2],如果aa[2]>aa[1],那么bb[2] = bb[1]+1,否则bb[2] = 1
(5)bb数组第三位,bb[3],如果aa[3]>aa[2]>aa[1] 那么bb[3] = bb[2]+1=3,否则如果aa[3]>aa[2] 则bb[3] = bb[2]+1,如果aa[3]>aa[1],则bb[3] = bb[1] +1,如果 aa[3]<aa[2] 且aa[3]<aa[1],bb[3] =1
(6)可以得出公式,bb[i] =max( bb[j] )+1 。 j 从1到 i -1,并且aa[i]>aa[j]
(7)构造最大长度,引入数组pre,pre第i位的含意是,到第 i 位为止,最大长度bb[i]是与第几位加1得来的。例如第五位,bb[5] =4 ,表示到第五位为止,最大长度为4,pre[5] =4 指bb[5]的最大长度4,是第4位加1得到的。
实现
(1)两层for循环,规划出bb数组
(2)lab 标记最大长度 在哪,方便到时候去构造
(3)利用pre数组,构造出最长增长序列,cc数组保存
import java.util.Scanner;
public final class LIS {
static int[] aa ;
static int[] bb ;
static int[] pre ;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
aa = new int[n+1];//第一位 aa[0] 没有使用,下面两个数组同理。
bb = new int[n+1];
pre = new int[n+1];
for (int i = 1; i <= n; i++) {
aa[i] = sc.nextInt();
}
System.out.println(solve());
}
}
private static int solve() {
int MaxLength,max=0,lab=0;//lab标记第几个 是最大长度
bb[1] = 1;//bb数组第i位 表示 从第1位到第i位为止,最大长度
pre[1]=0;//假设到第i位为止,最大长度为3 ,那么pre的第i位为4表示,
//最大长度2 从第4位来。
for (int i = 2; i < aa.length; i++) {
MaxLength=0;
for (int j = i-1; j >= 1; j--) {
if(aa[i]>aa[j]&&bb[j]>MaxLength) {
MaxLength = bb[j];
pre[i]=j;//MaxLength 从数组哪个位置
//得来的,方便之后构造。
}
}
bb[i] = MaxLength+1;
if(bb[i]>max) {
max=bb[i];
lab=i;
}
}
int[] cc = new int[max];//保存构造的数组。
//构造
int i=lab;
int j=max-1;
while(--lab!=0) {
cc[j] = aa[i];
j--;
i = pre[i];
}
//print
for(int z=1;i<cc.length;i++) {
System.out.print(cc[i]+" ");
}
System.out.println();
//返回最大长度。
return max;
}
}