leetcode
leetcode 551 ~ 600
最长连续递增序列

最长连续递增序列

难度:

标签:

题目描述

代码结果

运行时间: 18 ms, 内存: 16.9 MB


/*
 * 使用Java Stream API求解:
 * 将数组转换为一个列表,然后使用stream和reduce方法来计算最长的连续递增序列长度。
 */
import java.util.*;
import java.util.stream.*;
 
public class Solution {
    public int findLengthOfLCIS(int[] nums) {
        if (nums.length == 0) return 0;
        return IntStream.range(1, nums.length)
                .map(i -> nums[i] > nums[i - 1] ? 1 : -i)
                .mapToObj(n -> n > 0 ? n : -n)
                .reduce(1, (a, b) -> (b == 1) ? a + 1 : 1, Math::max);
    }
}

解释

方法:

这个题解采用了双指针的思路。左指针 left 表示当前连续递增子序列的起始位置,右指针 right 用于遍历数组。通过比较当前元素与前一个元素的大小,可以判断是否仍然保持递增趋势。如果递增,则更新最长长度 longest。如果递增中断,则更新 left 指针到当前位置,表示重新开始寻找连续递增子序列。最后返回找到的最长连续递增子序列的长度 longest。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中,为什么在递增中断时,最长长度需要使用 right-left 而不是 right-left+1 来计算?
这实际上是题解中的一个错误。在递增中断时,正确的做法应该是使用 `right-left+1` 来计算长度,因为 `left` 和 `right` 之间的距离需要包括 `left` 所指向的元素。例如,如果 `left` 指向索引 0 而 `right` 指向索引 1,此时子序列包含两个元素,应该使用 `right-left+1` 计算长度为 2。
🦆
如果数组中所有元素相同,如 [2,2,2,2,2],题解中的方法是否能正确处理并返回长度为1?
是的,题解中的方法能正确处理这种情况并返回长度为 1。因为每次当 `nums[right]` 不大于 `nums[right-1]` 时,左指针 `left` 会更新到 `right` 的位置,因此对于所有相同元素的数组,每次比较都会导致 `left` 更新,每个独立元素都被视为长度为 1 的连续递增子序列。
🦆
题解中提到,如果序列只有一个元素,直接返回1。这种处理方式是否可以被视为一个通用的边界条件处理,即对所有长度为1的数组直接返回1?
是的,这是一个通用的边界条件处理。对于任何长度为 1 的数组,由于没有其他元素与之比较,这单个元素自成一段连续递增子序列,长度自然为 1。这种处理是简洁且有效的,适用于所有长度为 1 的数组情况。
🦆
在题解的代码实现中,存在对最长长度longest的更新操作在两个不同的地方:递增时和递增中断时。这种重复的更新逻辑是否可以优化以简化代码?
是的,代码中的更新逻辑可以进行优化以简化代码。可以在循环结束后进行一次更新,而不是在循环的每个步骤中都进行。具体来说,可以在循环外部再添加一次 `longest = max(longest, right - left + 1)` 的操作,以确保最后一个连续递增子序列也被计算在内。这样,就无需在每个递增和中断点都更新 `longest`,从而简化代码。

相关问题

最长递增子序列的个数

给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。

注意 这个数列必须是 严格 递增的。

 

示例 1:

输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。

示例 2:

输入: [2,2,2,2,2]
输出: 5
解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。

 

提示: 

  • 1 <= nums.length <= 2000
  • -106 <= nums[i] <= 106

最小窗口子序列

最小窗口子序列