1. 问题描述:求解最长递增子序列的长度
输入:第一行输入的是数组的长度
第二行开始输入的是数组中的元素
输出:最长递增子序列的长度
输入 4 2 3 1 5 6
输出 4 (因为 2 3 5 6组成了最长递增子序列)
2. 使用之前的动态规划的解法的时间复杂度还是有点高,为O(n ^ 2),于是有人又想出了动态规划另外的优化解法,我们可以借鉴其中的思路来开拓我们的思维和更好地理解动态规划
思路是:dp[i]表示的是长度为i的最长递增子序列的末尾的那个数
举个例子:先初始化dp[0]为数组中第一个元素的值,即dp[0] = 4,定义一个指针p用来记录当前递增子序列的位置,从数组的第二个元素开始比较当前arr[i]与当前指针指向的dp数组的位置的值的大小,假如arr[i] > dp[p]那么说明当前的字符可以构成更长的递增子序列那么我们应该更新dp数组,指针往下移动,然后把当前的arr[i]的值赋值给dp[++p],假如arr[i] < dp[p]说明当前字符不能够构成更长的递增子序列,此时需要进行元素的替换,为什么进行替换呢?因为当前更小的元素更有利于最长递增子序列的贡献,所以扫描dp数组指向位置以及之前的位置假如arr[i] 大于dp[p]那么我们将其dp[p] 替换为arr[i]
最后返回的是指针p指向的位置,这也是与之前动态规划的一般解法不同的点
3. 具体的代码如下:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for(int i = 0; i < n; i++){
arr[i] = sc.nextInt();
}
System.out.println(solution(arr));
sc.close();
}
private static int solution(int[] arr){
int dp[] = new int[arr.length + 1];
dp[1] = arr[0];
int p = 1;
for(int i = 1; i < arr.length; i++){
if(arr[i] > dp[p]){
dp[++p] = arr[i];
}else{
for(int j = 0; j <= p; j++){
if(dp[j] > arr[i]){
dp[j] = arr[i];
}
}
}
}
return p;
}
}