文章起笔:2021年11月14日16:48:05
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 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。
提示:
1 <= nums.length <= 104
-109 <= nums[i] <= 109
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
本题和之前做过的一道题很像:
参考:【算法-LeetCode】300. 最长递增子序列(动态规划)_赖念安的博客-CSDN博客
但是本题的要求更简单一点,上面的题目中要求的递增子序列不是连续的,而本题中的递增子序列则要求是连续的。大体思路还是差不多的,但是本题会更简单一点。
第一反应就是利用动态规划的思想。有关动态规划的思路总结可以看下面的这篇博客:
参考:【算法-LeetCode】53. 最大子序和(动态规划初体验)_赖念安的博客-CSDN博客
本题的动态规划思路大体也是遵循上面提到的那种套路。
dp
数组的含义:dp[i]
代表截止至 nums[i]
,nums
数组中所能找到的最长的递增序列的长度。dp
数组的初始化。nums[i]
比前一个元素 nums[i-1]
大,那么就说明可以将当前遍历元素加入当前递增序列中,此时就有 dp[i] = dp[i-1] + 1
。nums[i]
小于等于前一个元素 nums[i-1]
,那么就说明不可以将当前遍历元素加入当前递增序列中,此时要重新开始寻找一个新的递增序列了,而这个新的递增序列的第一个元素就是当前遍历元素,所以此时就有 dp[i] = 1
。dp[i-1]
,为了防止下标溢出,所以需要根据 dp
数组的定义来对 dp[0]
做初始化操作:dp[0] = 1
。dp[i]
后,都应该更新 maxLen
的值为最大值。所以我们最后其实是要返回 dp
数组中的最大值。(这一点和上面提到的『【算法-LeetCode】53. 最大子序和』中的思路其实是一样的)/**
* @param {number[]} nums
* @return {number}
*/
var findLengthOfLCIS = function(nums) {
// maxLen用于记录目前在nums数组中所能找到的最长的连续递增序列的长度
let maxLen = 1;
let dp = [];
// 初始化dp数组
dp[0] = 1;
// 开始由前向后遍历nums数组,注意是从 i=1 处开始遍历的
for(let i = 1; i < nums.length; i++) {
// 若发现满足递增条件,则根据前序递增长度推导出当前递增长度,否则就直接从头寻找递增序列
dp[i] = nums[i] > nums[i-1] ? dp[i-1] + 1 : 1;
// 每次计算完dp[i]后都应该更新maxLen的值,以保证maxLen是dp数组中的最大值
maxLen = Math.max(maxLen, dp[i]);
}
return maxLen;
};
提交记录
执行结果:通过
35 / 35 个通过测试用例
执行用时:68 ms, 在所有 JavaScript 提交中击败了80.07%的用户
内存消耗:40.2 MB, 在所有 JavaScript 提交中击败了5.00%的用户
时间:2021/11/14 16:50
这道题也可以用贪心的思想来做,也就是尽量地扩展递增序列的长度,并保留最长的那个递增序列的长度。
其实这道题就和之前的那道『【算法-LeetCode】122. 买卖股票的最佳时机 II』中的贪心思想有点像,本质都是在找一段递增区间。
一开始我没有考虑到当 nums
中的元素都是递增序列时的情况,所以提交后出现了下面这种情况:
执行结果:解答错误
通过测试用例:25 / 35
输入:[1,3,5,7]
输出:1
预期结果:4
这是因为当 nums
中的元素都是递增序列时,则下面的 if
判断中的更新语句不会被执行,当遍历完成后,maxLen
仍然保持为初始值 1
。
所以我就在下面的 if
判断中增加了相应的判断条件:当遍历到 nums
末尾时,必须做一次更新操作。
/**
* @param {number[]} nums
* @return {number}
*/
var findLengthOfLCIS = function(nums) {
let maxLen = 1;
// front指针指向一个连续递增区间的开头位置
let front = 0;
// back指针指向一个连续递增区间的末尾位置,同时back指针也充当遍历nums时的迭代指针
for(let back = 0; back < nums.length; back++) {
// 如果遍历过程中发现了不满足连续递增的条件,则更新一下maxLen以及下一个递增区间的开始
// 位置,注意第二个判断条件是为了应对 nums 中的元素从头到尾都是递增序列的情况
if(nums[back] >= nums[back + 1] || back === nums.length - 1) {
maxLen = Math.max(maxLen, back - front + 1);
front = back + 1;
}
}
return maxLen;
};
提交记录
执行结果:通过
35 / 35 个通过测试用例
执行用时:68 ms, 在所有 JavaScript 提交中击败了80.07%的用户
内存消耗:38.7 MB, 在所有 JavaScript 提交中击败了41.95%的用户
时间:2021/11/14 17:01
更新:2021年7月29日18:43:21
因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。
【更新结束】
更新:2021年11月14日17:06:05
参考:674. 最长连续递增序列 题解 - 力扣(LeetCode)
【更新结束】
更新:2021年11月14日17:20:51
参考:【算法-LeetCode】53. 最大子序和(动态规划初体验)_赖念安的博客-CSDN博客
更新:2021年11月14日17:28:36
参考:【算法-LeetCode】122. 买卖股票的最佳时机 II(动态规划;贪心)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】300. 最长递增子序列(动态规划)_赖念安的博客-CSDN博客