0%

leetcode每日一题2020.1.24

674. 最长连续递增序列

一、题目

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 lr(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
};
万一真有土豪呢