【算法-LeetCode】674. 最长连续递增序列(动态规划;贪心;双指针)

674. 最长连续递增序列 - 力扣(LeetCode)

文章起笔: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博客

但是本题的要求更简单一点,上面的题目中要求的递增子序列不是连续的,而本题中的递增子序列则要求是连续的。大体思路还是差不多的,但是本题会更简单一点。

我的题解1(动态规划)

第一反应就是利用动态规划的思想。有关动态规划的思路总结可以看下面的这篇博客:

参考:【算法-LeetCode】53. 最大子序和(动态规划初体验)_赖念安的博客-CSDN博客

本题的动态规划思路大体也是遵循上面提到的那种套路。

  1. 首先明白 dp 数组的含义:dp[i] 代表截止至 nums[i]nums 数组中所能找到的最长的递增序列的长度。
  2. 然后是确定状态转移方程和 dp 数组的初始化。
    如果当前遍历元素 nums[i] 比前一个元素 nums[i-1] 大,那么就说明可以将当前遍历元素加入当前递增序列中,此时就有 dp[i] = dp[i-1] + 1

    如果当前遍历元素 nums[i] 小于等于前一个元素 nums[i-1],那么就说明不可以将当前遍历元素加入当前递增序列中,此时要重新开始寻找一个新的递增序列了,而这个新的递增序列的第一个元素就是当前遍历元素,所以此时就有 dp[i] = 1
  3. 因为在状态转移方程中用到了 dp[i-1],为了防止下标溢出,所以需要根据 dp 数组的定义来对 dp[0] 做初始化操作:dp[0] = 1
  4. 最后每次计算得出 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

我的题解2(贪心;双指针)

这道题也可以用贪心的思想来做,也就是尽量地扩展递增序列的长度,并保留最长的那个递增序列的长度。

其实这道题就和之前的那道『【算法-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博客

你可能感兴趣的:(LeetCode,动态规划,leetcode,贪心算法,双指针,javascript)