一、题目 给定一个未经排序的整数数组,找到最长且 连续递增的子序列 ,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l
和 r(l < r)
确定,如果对于每个 l <= i < r
,都有 nums[i] < nums[i + 1]
,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]]
就是连续递增子序列。
示例1:
1 2 3 4 输入:nums = [1,3,5,4,7] 输出:3 解释:最长连续递增序列是 [1,3,5], 长度为3。 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
示例2:
1 2 3 输入:nums = [2,2,2,2,2] 输出:1 解释:最长连续递增序列是 [2], 长度为1。
提示:
0 ≤ nums.length ≤ $10^4$
-$10^9$ ≤ nums[i] ≤ $10^9$
二、题解 方法1:动态规划 1 2 3 4 5 6 dp矩阵的定义 dp[i] 定义为以 nums[i] 结尾的连续递增子序列的最大长度 转移方程很好理解,dp[i-1] --> dp[i] 如果 nums[i] > nums[i-1],那么 dp[i] = dp[i-1] + 1,也就是与前面的组成连续递增子序列 否则的话,nums[i] 自成一组连续递增子序列,即 dp[i] = 1
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(n)
1 2 3 4 5 6 7 8 9 10 11 var findLengthOfLCIS = function (nums ) { if (!nums.length) return 0 ; const n = nums.length; let dp = Array (n).fill(1 ); for (let i=1 ; i<n; i++) { if (nums[i] > nums[i-1 ]) { dp[i] = dp[i-1 ] + 1 ; } } return Math .max(...dp) };
方法2:贪心 1 2 3 4 5 6 用一个 start 指针记录连续递增子序列的头部位置,初始时 start = 0,然后遍历数组进行如下操作: 1. 如果下标 nums[i] ≤ nums[i−1],则说明当前元素小于或等于上一个元素,因此 nums[i−1] 和 nums[i] 不可能属于同一个连续递增序列, 必须从下标 i 处开始一个新的连续递增序列,因此令 start=i。如果下标 i=0 或 nums[i] > nums[i−1],则不更新 start 的值。 2.此时下标范围 [start,i] 的连续子序列是递增序列,其长度为 i−start+1,使用当前连续递增序列的长度更新最长连续递增序列的长度。
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(1)
1 2 3 4 5 6 7 8 9 10 11 var findLengthOfLCIS = function (nums ) { let start = 0 ; let ret = 0 ; for (let i=0 ; i<nums.length; i++) { if (i > 0 && nums[i] <= nums[i-1 ]) { start = i; } ret = Math .max(ret, i - start + 1 ) } return ret };