• 最长递增子序列


    题目描述

    给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

    示例

    示例1

    输入:nums = [10,9,2,5,3,7,101,18]
    输出:4
    解释:最长递增子序列是 [2,3,7,101],因此长度为 4
    • 1
    • 2
    • 3

    示例2

    输入:nums = [0,1,0,3,2,3]
    输出:4
    
    • 1
    • 2

    示例3

    输入:nums = [7,7,7,7,7,7,7]
    输出:1
    
    • 1
    • 2

    思路

    定义dp[i]表示以第i个元素为结尾的最长上升子序列的长度。

    代码如下

    	public int lengthOfLISNormal1(int[] nums) {
            int n = nums.length;
            if(n == 0 || n == 1) return n;
            // dp[i]表示以第i个元素为结尾的最长上升子序列的长度。
            int[] dp = new int[n];
            Arrays.fill(dp, 1);
            int res = 1;
            for(int i = 1;i < n;i++){
                for(int j = 0;j < i;j++){
                    if(nums[i] > nums[j]){
                        // dp[j] + 1 表示在以 nums[j] 结尾的上升子序列的末尾添加当前元素
                        //  nums[i] 后,得到的新的上升子序列长度为 dp[j] + 1。因为当前元
                        // 素 nums[i] 可能可以添加到以 nums[j] 结尾的上升子序列中,所以需
                        // 要比较加入当前元素后子序列的长度是否更长,如果更长则更新当前
                        // dp[i] 的值。
                        dp[i] = Math.max(dp[i],dp[j] + 1);
                    }
                }
                res = Math.max(res, dp[i]);
            }
            return res;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    输出最长递增子序列

    代码1

    	public List<Integer> printLengthOfLISNormal(int[] nums) {
            int n = nums.length;
            // dp[i]表示以第i个元素为结尾的最长上升子序列的长度。
            List<Integer>[] dp = new List[nums.length];
            for (int i = 0; i < n; i++) {
                dp[i] = new ArrayList<>();
            }
            dp[0].add(nums[0]);
            for(int i = 1;i < n;i++){
                int index = -1, maxLen = 0;
                for(int j = 0;j < i;j++){
                    if(nums[i] > nums[j] && dp[j].size() > maxLen){
                        maxLen = dp[j].size();
                        index = j;
                    }
                }
                if(index != -1){
                    dp[i].addAll(dp[index]);
                }
                dp[i].add(nums[i]);
            }
            List<Integer> res = dp[0];
            for (int i = 1; i < dp.length; i++) {
                if (res.size() < dp[i].size()) {
                    res = dp[i];
                }
            }
            return res;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    代码2

    	public List<Integer> printLengthOfLISNormal1(int[] nums) {
            int n = nums.length;
            int[] dp = new int[n];  // dp[i]表示以第i个元素为结尾的最长上升子序列的长度
            Arrays.fill(dp, 1);  // 初始时,每个元素自成一个子序列
    
            int maxLength = 1, endIndex = 0;  // 记录全局最长子序列的长度和结束位置
    
            for (int i = 1; i < n; i++) {
                for (int j = 0; j < i; j++) {
                    if (nums[i] > nums[j]) {
                        dp[i] = Math.max(dp[i], dp[j] + 1);
    
                        // 更新全局最长子序列的信息
                        if (dp[i] > maxLength) {
                            maxLength = dp[i];
                            endIndex = i;
                        }
                    }
                }
            }
    
            // 根据全局最长子序列的长度和结束位置,回溯构造最长上升子序列
            List<Integer> res = new ArrayList<>();
            for (int i = endIndex; i >= 0; i--) {
                if (dp[i] == maxLength) {
                    res.add(nums[i]);
                    maxLength--;
                }
            }
    
            Collections.reverse(res);  // 因为是逆序添加的,需要翻转一下得到正确顺序
            return res;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    AI 绘画基础 - 细数 Stable Diffusion 中的各种常用模型 【🧙 魔导士装备图鉴】
    netty系列之:kequeue传输协议详解
    【LeetCode】611.有效三角形的个数
    月薪3W,互联网“降本增效”后,这些人开始被疯抢
    人脸解锁设备时出现相机报错
    CAN总线协议的理解以及移植stm32代码并使用
    工程伦理考试题
    STM32在STM32CubeIDE平台下的RT-Thread Nano移植
    CSS基础入门
    快速删除包含指定数字的数据
  • 原文地址:https://blog.csdn.net/qq_41591215/article/details/134518292