当前位置: 首页 > article >正文

【Leetcode 热题 100】300. 最长递增子序列

问题背景

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

数据约束

  • 1 ≤ n u m s . l e n g t h ≤ 2500 1 \le nums.length \le 2500 1nums.length2500
  • − 1 0 4 ≤ n u m s [ i ] ≤ 1 0 4 -10 ^ 4 \le nums[i] \le 10 ^ 4 104nums[i]104

解题过程

子序列而不是子数组,优先考虑回溯法而不是滑窗。
递归方法中必须要有一个下标表示当前要选择的数字的位置,选或不选的方法还需要额外记录子序列中前一个数相关的信息,否则不能保证严格递增。因此,这题选择选哪一个的做法代码更简洁。

对于动态规划问题,有一种优化时间复杂度的方案是交换状态和状态值,这题可以在数组中维护子序列末尾元素的最小值,遍历数组的过程中只有两种操作:添加或修改元素。
修改的一定是不小于当前元素的第一个元素,如果没有这样的元素,就应将新元素添加到末尾。
配合二分查找,这样可以将时间效率优化到 O ( N l o g N ) O(NlogN) O(NlogN) 这个量级。

具体实现

递归

class Solution {
    private int[] nums;
    private int[] memo;

    public int lengthOfLIS(int[] nums) {
        this.nums = nums;
        int n = nums.length;
        memo = new int[n];
        int res = 0;
        for (int i = 0; i < n; i++) {
            res = Math.max(res, dfs(i));
        }
        return res;
    }

    private int dfs(int i) {
        if(memo[i] > 0) {
            return memo[i];
        }
        for (int j = 0; j < i; j++) {
            if(nums[j] < nums[i]) {
                memo[i] = Math.max(memo[i], dfs(j));
            }
        }
        return ++memo[i];
    }
}

递推

class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int res = 0;
        int[] dp = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i]) {
                    dp[i] = Math.max(dp[i], dp[j]);
                }
            }
            res = Math.max(res, ++dp[i]);
        }
        return res;
    }
}

贪心

class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int res = 0;
        int[] dp = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i]) {
                    dp[i] = Math.max(dp[i], dp[j]);
                }
            }
            res = Math.max(res, ++dp[i]);
        }
        return res;
    }
}

http://www.kler.cn/a/521084.html

相关文章:

  • python -m pip和pip的主要区别
  • 人工智能学习框架:深入解析与实战指南
  • SimpleFOC STM32教程10|基于STM32F103+CubeMX,速度闭环控制(有电流环)
  • 第4章 神经网络【1】——损失函数
  • 六、深入了解DI
  • 神经网络|(四)概率论基础知识-古典概型
  • [SWPUCTF 2022 新生赛]js_sign
  • 【java数据结构】哈希表
  • 2025年美赛数学建模F题 为农业再培养腾出空间
  • 葡萄果品分级以及葡萄簇识别-目标检测数据集
  • SOAFEE 技术研讨会:汽车软件定义与自动驾驶技术探讨
  • arduino学习
  • Kotlin单例类
  • LeetCode - Google 校招100题 第9天 Hard 题汇总 (12题)
  • 2025年数学建模美赛 A题分析(4)楼梯使用人数模型
  • Vuex 的核心概念:State, Mutations, Actions, Getters
  • 提供一种刷新X410内部EMMC存储器的方法
  • 【AI论文】Sigma:对查询、键和值进行差分缩放,以实现高效语言模型
  • AndroidStudio 下载链接
  • Blazor-@typeparam
  • C++资料
  • 序列标注:从传统到现代,NLP中的标签预测技术全解析
  • dev c++ ‘unordered_set‘ does not name a type
  • 工业数据分析:解锁工厂数字化的潜力
  • Pyecharts之饼图与多饼图的应用
  • .NET 8 项目 Docker 方式部署到 Linux 系统详细操作步骤