解题思路

动态规划方法,用长度n的dp记录所有元素的序列长度、序列末尾数字。首个dp值长度为1,末尾值为6。
后面的元素算dp时要遍历前面的dp点,找出最长并且序列末尾小于arr[i],可以添加在后面的dp点,长度+1。如果找不到,就添加一个长度1的dp点。添加时末尾序列改为arr[i]。
为了方便遍历,dp按序列长度从大到小排序。目前这个解题过程较乱,不好通过文字描述清楚,代码注释尽量详细写了过程。算法上也还有优化空间。

代码

import java.util.Scanner;
import java.util.LinkedList;
import java.util.List;
 
public class Main{
     
    public static void main(String[] args){
        int n;
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        int[] a = new int[n];
        
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }
        
        // dp记录<上升序列的末尾数字, 该序列长度>,按长度排序
        // <num, length>
        List<DP> dp = new LinkedList<>();

        dp.add(0, new DP(a[0], 1));

        for (int i = 1; i < n; i++) {
            // 前面记录的dp中是否有比a[i]小的数字
            boolean hasSmall = false;
            for (int j = 0; j < dp.size(); j++) {
                if (dp.get(j).num < a[i]) {
                    // 前面dp中有比a[i]小的数字,并且dp是按长度排序的,此处一定是最大子序列
                    int length = dp.get(j).length + 1;    // 序列长度+1
                    for (int k = 0; k < dp.size(); k++) {
                        // 插入dp时,按照length长度从大到小顺序插入
                        if (!(dp.get(k).length > length)) {
                            dp.add(k, new DP(a[i], length));
                            break;
                        }
                    }
                    hasSmall = true;
                    break;
                }
            }

            // 前面dp中没有比a[i]小的数字,把a[i]记为长度1
            if (!hasSmall) {
                dp.add(dp.size(), new DP(a[i], 1));
            }
        }
        
        System.out.println(dp.get(0).length);
    }
    
    public static class DP {
        public int num;
        public int length;

        public DP(int num, int length) {
            this.num = num;
            this.length = length;
        }
    }
}