300. 最长递增子序列
| 2024-5-6
0  |  阅读时长 0 分钟
From
Leetcode
Status
回头复习下
Date
Apr 23, 2024
Tags
动态规划
子序列问题
Difficulty
中等

题面

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的
子序列
示例 1:
示例 2:
示例 3:
提示:
  • 1 <= nums.length <= 2500
  • 104 <= nums[i] <= 104
进阶:
  • 你能将算法的时间复杂度降低到 O(n log(n)) 吗?
 

思路

动态规划之子序列问题入门题
 

题解

动态规划

贪心+二分

💡
比如序列是78912345,前三个遍历完以后tail是789,这时候遍历到1,就得把1放到合适的位置,于是在tail二分查找1的位置,变成了189(如果序列在此时结束,因为res不变,所以依旧输出3),再遍历到2成为129,然后是123直到12345
 
  1. tails数组的定义:tails数组是用来存储当前找到的最长递增子序列的尾部元素。在任意时刻,tails[k]的值代表长度为k+1的最长递增子序列的尾部元素的最小值。
  1. 变量res表示当前发现的最长递增子序列的长度。
  1. 循环遍历nums数组:
  • 对于每个元素num,使用二分查找在tails数组中找到num应该插入的位置,即tails数组中第一个大于等于num的元素的位置。
  • 二分查找的范围是[0, res),其中i是左边界,j是右边界。
  1. 二分查找过程:
  • 计算中点m = (i + j) / 2。
  • 如果tails[m] < num,则说明num应该在m之后的位置,因此更新左边界i = m + 1。
  • 否则,num应该在m或之前的位置,因此更新右边界j = m。
  1. 更新tails数组:
  • 找到的i即是num应该插入的位置。将tails[i]更新为num。
  • 如果num的插入位置i等于当前递增子序列长度res,意味着num可以作为一个新的、更长的递增子序列的尾部,因此res自增1。
  1. 循环结束后,变量res即为最长递增子序列的长度。
Loading...
目录