class Solution {
    public List<Integer> getLIS(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        
        // 【新增】用来记录前驱节点的索引,-1 表示没有前面没有接人
        int[] prev = new int[n]; 
        for(int k = 0 ; k < n ; k++) {
            dp[k] = 1;
            prev[k] = -1; // 默认都没有老大哥
        }
        
        int maxLen = 1;
        int maxIndex = 0; // 【新增】记录最长子序列是以哪个索引结尾的
        
        for(int i = 1 ; i < n ; i++){
            int maxLength = 0;
            int bestJ = -1; // 【新增】记录到底接在哪个 j 后面最划算
            
            for(int j = i - 1; j >= 0 ; j--){
                // 注意这里:不能单纯用 Math.max 了,因为我们要知道具体的 j 是谁
                if(nums[j] < nums[i] && dp[j] > maxLength){ 
                    maxLength = dp[j];
                    bestJ = j; // 记住最牛老大哥的名字(索引)
                }
            }
            dp[i] = maxLength + 1;
            prev[i] = bestJ; // 正式把老大哥登记在册
            
            // 顺手更新全局最大值,并记下这个巅峰是属于谁的(maxIndex)
            if (dp[i] > maxLen) {
                maxLen = dp[i];
                maxIndex = i;
            }
        }
        
        // 【新增阶段】顺藤摸瓜,收集结果
        List<Integer> res = new ArrayList<>();
        int curr = maxIndex; // 从巅峰位置开始往回回溯
        
        while (curr != -1) {
            res.add(nums[curr]); // 把当前数字收进袋子
            curr = prev[curr];   // 顺着线索找上一个老大哥
        }
        
        // 因为我们是倒着往回找的,所以收集到的序列是反的,翻转过来!
        Collections.reverse(res); 
        
        return res;
    }
}

两块二每分钟