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

LeetCode算法日记 - Day 91: 最长数对链

目录

1. 最长数对链

1.1 题目解析

1.2 解法

1.3 代码实现


1. 最长数对链

给你一个由 n 个数对组成的数对数组 pairs ,其中 pairs[i] = [lefti, righti] 且 lefti < righti 。

现在,我们定义一种 跟随 关系,当且仅当 b < c 时,数对 p2 = [c, d] 才可以跟在 p1 = [a, b] 后面。我们用这种形式来构造 数对链 。

找出并返回能够形成的 最长数对链的长度 。

你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。

示例 1:

输入:pairs = [[1,2], [2,3], [3,4]]
输出:2
解释:最长的数对链是 [1,2] -> [3,4] 。

示例 2:

输入:pairs = [[1,2],[7,8],[4,5]]
输出:3
解释:最长的数对链是 [1,2] -> [4,5] -> [7,8] 。

提示:

  • n == pairs.length
  • 1 <= n <= 1000
  • -1000 <= lefti < righti <= 1000

1.1 题目解析

题目本质
这是一个"最长递增子序列"的变体问题。给定多个区间(数对)(i - j),要求选出最多的区间,使得它们能按照"前一个区间的右端点 < 后一个区间的左端点"的规则连接成链。

常规解法
最直观的想法是枚举所有可能的数对组合,检查哪些能形成合法的链,然后找出最长的那条。可以用回溯或暴力搜索来实现。

class Solution {private int maxLen = 0;public int findLongestChain(int[][] pairs) {boolean[] used = new boolean[pairs.length];backtrack(pairs, used, -1001, 0);return maxLen;}private void backtrack(int[][] pairs, boolean[] used, int lastRight, int len) {maxLen = Math.max(maxLen, len);for(int i = 0; i < pairs.length; i++) {if(!used[i] && pairs[i][0] > lastRight) {used[i] = true;backtrack(pairs, used, pairs[i][1], len + 1);used[i] = false;}}}}

问题分析
暴力枚举的时间复杂度是 O(2^n),当 n=1000 时,会产生天文数字级别的计算量,完全不可行。我们需要找到问题的"最优子结构"来避免重复计算。

思路转折
观察到:如果我们已经知道"以某个数对结尾的最长链长度",那么后续数对只需要判断能否连接到这个数对上即可。
这提示我们可以用动态规划:将大问题分解为"以第 i 个数对结尾的最长链"的子问题。但前提是要先排序,这样才能保证遍历时已经处理过所有可能的前驱。更进一步,这个问题类似"活动选择问题",可以用贪心算法达到更优的 O(n log n) 复杂度。

1.2 解法

 算法思想          

采用动态规划 + 区间排序:
先按右端点升序排序(贪心思想:右端点越小,后面能接的数对越多)
定义 dp[i] = 以 pairs[i] 结尾的最长链长度状

态转移方程:

dp[i] = Math.max(dp[i], dp[j] + 1);

    i)排序:按右端点升序排列所有数对

    ii)初始化:dp[i] = 1(每个数对单独都能组成长度为 1 的链)

    iii)状态转移:

    • 对于每个 pairs[i],向前遍历所有 pairs[j](j < i)

    • 如果 pairs[j][1] < pairs[i][0],说明 pairs[i] 可以接在 pairs[j] 后面

    • 更新 dp[i] = max(dp[i], dp[j] + 1)

    iv)求答案:遍历 dp 数组,找最大值

    易错点

    • 排序依据:必须按右端点排序,而不是左端点。因为右端点越小,给后续数对留的空间越大(贪心思想)

    • 连接条件:是 pairs[j][1] < pairs[i][0],注意是严格小于,不能等于。题目定义的跟随关系是 b < c

    • 初始化:dp[i] 初始化为 1,不是 0。因为每个数对单独都能组成一条长度为 1 的链

    • 遍历顺序:外层循环从 1 开始(因为 dp[0] 已经是 1),内层循环从 0 到 i-1

    1.3 代码实现

    // 最长数对链
    static class Solution {public int findLongestChain(int[][] pairs) {int n = pairs.length;// 按右端点排序(贪心:右端点越小,后面能接的越多)Arrays.sort(pairs, (a, b) -> a[1] - b[1]);// dp[i] 表示以 pairs[i] 结尾的最长链长度int[] dp = new int[n];Arrays.fill(dp, 1);// 状态转移for (int i = 1; i < n; i++) {for (int j = 0; j < i; j++) {// 如果 pairs[i] 能接在 pairs[j] 后面if (pairs[j][1] < pairs[i][0]) {dp[i] = Math.max(dp[i], dp[j] + 1);}}}// 找最大值int ret = 1;for (int i = 0; i < n; i++) {ret = Math.max(ret, dp[i]);}return ret;}
    }

    复杂度分析

    • 时间复杂度:O(n²)

    • 空间复杂度:O(n)

    http://www.dtcms.com/a/564682.html

    相关文章:

  1. 潍坊哪个网站建设公司好wordpress刷新才显示
  2. 在 Hive 中NULL的理解
  3. 如何让UE5的插件Ultra Dynamic Sky的光照对齐真实时间?
  4. 【问题解决】用pnpm创建的 Vue3项目找不到 .eslintrc.js文件 及 后续的eslint配置的解决办法
  5. Kubernetes Pod 基本原理:全面详解
  6. 有关于cnb自动化的脚本补全
  7. Hive三大连接操作全解析
  8. css3新增过渡
  9. Hive 中的 COALESCE 函数作用
  10. 网站建设内部下单流程图赣州的免费网站建设
  11. 广东顺德网站建设instagram wordpress
  12. Linux连接Doris:MySQL与Beeline指南
  13. 【金仓数据库】ksql 指南(四) —— 创建与管理表(KingbaseES 数据存储核心)
  14. Swift项目生成Framework流程以及与OC的区别
  15. C++多线程同步与互斥
  16. Python Jupyter Notebook 完全指南:从入门到精通
  17. 站点查询wordpress 外贸网站
  18. CSP集训错题集 第八周 主题:基础图论
  19. 基于C语言 HTTP 服务器客户端的实验
  20. 如何利用 Jupyter 从浏览器访问远程服务器
  21. C语言基础知识点简单案例分享之二——C语言全知识点速查宝典
  22. 怎么找网站局域网电脑做网站服务器
  23. 一男一女做那个的动漫视频网站网站怎样推广 优帮云
  24. hive常用命令
  25. AWS + 飞天CMS:高性能内容站的云端搭建方案
  26. 800G光模块:驱动AI与云计算高速互联的核心引擎
  27. Python每日一练---第三天:删除有序数组中的重复项
  28. U-Net 的输入与输出:通用场景与扩散模型场景解析
  29. 李宏毅机器学习笔记39
  30. 【代码随想录算法训练营——Day57(Day56周日休息)】图论——53.寻宝