674. 最长连续递增序列 - 力扣(LeetCode)
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l
和 r
(l < r
)确定,如果对于每个 l <= i < r
,都有 nums[i] < nums[i + 1]
,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]]
就是连续递增子序列。
示例 1:
输入:nums = [1,3,5,4,7] 输出:3 解释:最长连续递增序列是 [1,3,5], 长度为3。 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
示例 2:
输入:nums = [2,2,2,2,2] 输出:1 解释:最长连续递增序列是 [2], 长度为1。
>>思路和分析
本题相对于leetCode 300.最长递增子序列 最大区别在于 “连续”
- 不连续递增子序列的跟前0-i 个状态有关(两个for循环)
- 连续递增的子序列只跟前一个状态有关(一个for循环)
>>方法一:动态规划
1.确定dp数组(dp table)以及下标的含义
- dp[i]:以下标i为结尾的连续递增的子序列长度为dp[i]
注意这里的定义,一定是以下标i为结尾,并不是说一定以下标0为起始位置。
2.确定递推公式
如果 nums[i] > nums[i - 1],那么以 i 为结尾的连续递增的子序列长度 一定等于 以i - 1为结尾的连续递增的子序列长度 + 1
- 即:dp[i] = dp[i - 1] + 1;
3.dp数组初始化
以下标i为结尾的连续递增的子序列长度最少也应该是1,即就是nums[i]这一个元素。所以dp[i]应该初始1;
4.确定遍历顺序
从递推公式上可以看出, dp[i + 1]依赖dp[i],所以一定是从前向后遍历
for (int i = 1; i < nums.size(); i++) {
if (nums[i] > nums[i - 1]) { // 连续记录
dp[i] = dp[i - 1] + 1;
}
}
5.举例推导dp数组
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
if (nums.size() == 0) return 0;
int result = 1;
vector<int> dp(nums.size() ,1);
for (int i = 1; i < nums.size(); i++) {
if (nums[i] > nums[i - 1]) { // 连续记录
dp[i] = dp[i - 1] + 1;
}
if (dp[i] > result) result = dp[i];
}
return result;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(n)
>>方法二:贪心策略
当遇到nums[i] > nums[i - 1]的情况,count++,否则count 为 1,记录下count的最大值即可
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
if (nums.size() == 0) return 0;
int count=1;
int result=1;// 连续子序列最少也是1
for(int i=1;i<nums.size();i++) {
// 连续记录
if(nums[i]>nums[i-1]) count = count + 1;
// 不连续,count从头开始
else count=1;
result = max(count,result);
}
return result;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
>>来自代码随想录课堂截图:
>>参考和推荐文章、视频
代码随想录 (programmercarl.com)
动态规划之子序列问题,重点在于连续!| LeetCode:674.最长连续递增序列_哔哩哔哩_bilibili