线性dp:LeetCode674. 最长连续递增序列
LeetCode674. 最长连续递增序列
- 阅读本文之前,需要先了解“动态规划方法论”,这在我的文章以前有讲过
- 本文之前也讲过一篇文章:最长递增子序列,这道题,阅读本文的同时可以与“最长递增子序列进行对比”,这样更能对比二者的区别!
LeetCode300.最长递增子序列 - Tomorrowland_D - 博客园 (cnblogs.com)
- 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。
提示:
- 0 <= nums.length <= 10^4
- -10^9 <= nums[i] <= 10^9
动态规划思路讲解:
- 这道题与[最长递增子序列](LeetCode300.最长递增子序列 - Tomorrowland_D - 博客园 (cnblogs.com))的区别就是,最长递增子序列是可以不连续的,而最长连续递增序列必须要是连续的。
- 我们这道题仍然可以采用dp[i]的思想,而这里的dp[i]与最长递增子序列的dp[i]就差不多了,但不是完全一致
状态变量及其含义
- 我们可以设置状态变量dp[i],表示以nums[i]为结尾的最长连续子序列的长度
递推公式
-
这里我们不需要j指针,只需要将
nums[i]与nums[i-1]
作比较,判断它们两个是否能继续构成连续递增子序列,如果nums[i]<nums[i-1]
,证明nums[i]
不能与nums[i-1]
构成连续递增子序列,所以说dp[i]=0
-
当
nums[i]>nums[i-1]
时,意味nums[i]与前面能继续构成连续递增子序列,所以dp[i]=dp[i-1]+1
-
故而递推公式为:
dp[i]=0 (nums[i]<=nums[i-1]);
dp[i]=dp[i-1]+1 (nums[i]>nums[i-1])
遍历顺序
- 这题dp[i]需要由dp[i-1]来推理出来,所以说遍历顺序显然是从前向后遍历。
如何初始化dp数组?
- 显然,一开始dp数组中的所有元素都初始化为1,因为每个元素至少都有一个最长连续递增子序列。
举例验证dp数组
- 举例:nums = [1,3,5,4,7]
- dp[0]=1
- dp[1]=2
- dp[2]=3
- dp[3]=0
- dp[4]=2
- 通过示例1的分析,我们也可以得知我们的dp数组是正确的
代码实现:
class Solution {
public:
int findLengthOfLCIS(vector<int>& nums) {
//全都初始化为1
vector<int> dp(nums.size(),1);
//结果至少是1
int ans=1;
for(int i=1;i<nums.size();i++){
if(nums[i]>nums[i-1]) dp[i]=dp[i-1]+1;
ans=max(ans,dp[i]);
}
return ans;
}
};