AI刷题-稳定数组的最长子数组长度 | 青训营笔记

132 阅读4分钟

问题描述

小R定义一个数组为“稳定的”,当且仅当数组中相邻两个元素之差的绝对值不超过1。例如,数组 [2,3,2,2,1] 是稳定的,而 [1,3,2] 则不是。小R拿到一个数组,她想知道这个数组中最长的“稳定的”连续子数组的长度是多少。你能帮她解答吗?


测试样例

样例1:

输入:n = 5 ,a = [2, 4, 2, 3, 2]
输出:3

样例2:

输入:n = 6 ,a = [1, 2, 2, 3, 4, 1]
输出:5

样例3:

输入:n = 7 ,a = [5, 5, 6, 7, 7, 6, 5]
输出:7

问题分析

给定一个数组,要求我们找到最长的连续子数组,使得该子数组中的相邻两个元素之差的绝对值不超过1。换句话说,若对于一个子数组中的每一对相邻元素 a[i]a[i+1],满足 |a[i] - a[i+1]| <= 1,则这个子数组是“稳定的”。我们的目标是求出数组中最长的稳定子数组的长度。

思路分析

  1. 条件分析

    • 数组中每一对相邻元素的差的绝对值不超过1。
    • 我们需要找出最长的连续子数组,满足上述条件。
  2. 滑动窗口/双指针思路

    • 我们可以使用滑动窗口的技巧,通过一个指针遍历整个数组,保持一个区间 [start, end],其中 a[start]a[end] 是一个稳定的子数组。
    • 如果当前元素 a[end] 和前一个元素 a[end-1] 之间的差的绝对值大于 1,说明这个子数组不稳定,需要调整窗口的起始位置 start
    • 每次遍历时记录当前稳定子数组的长度,最终输出最大的稳定子数组长度。
  3. 具体步骤

    • 使用两个指针:startend,初始化时都指向数组的第一个元素。

    • 维护一个变量 max_len 来记录当前找到的最长稳定子数组的长度。

    • 遍历数组,对于每一个新元素 a[end]

      • 如果 |a[end] - a[end-1]| > 1,说明从 startend 的子数组不稳定,需要移动 start 指针,直到 a[start]a[end] 之间满足稳定条件。
      • 如果是稳定的,则继续扩大 end 指针,并更新 max_len
  4. 边界条件

    • 如果数组长度为 1,直接返回 1,因为任何单元素数组都是稳定的。

代码实现

python
Copy code
def longestStableSubarray(n, a):
    # 初始化变量
    start = 0  # 左指针
    max_len = 1  # 最长稳定子数组的长度
    for end in range(1, n):  # 右指针
        # 如果当前元素和前一个元素之差大于1,则调整start指针
        while abs(a[end] - a[end - 1]) > 1:
            start += 1  # start向右移动
        # 更新最长稳定子数组的长度
        max_len = max(max_len, end - start + 1)
    return max_len

解释

  1. 初始化

    • start 为子数组的起始位置,初始值为 0。
    • max_len 用于记录最长稳定子数组的长度,初始化为 1,因为单个元素子数组至少是稳定的。
  2. 滑动窗口逻辑

    • end 从 1 开始遍历数组,表示当前的右边界。
    • 对于每个 end,检查 |a[end] - a[end-1]| 是否大于 1。如果大于 1,说明从 startend 的子数组不稳定,需要移动 start,直到区间 [start, end] 是稳定的。
    • 每次移动 end 时,更新 max_len,确保记录最大长度。
  3. 返回值

    • 最后返回 max_len,即最长稳定子数组的长度。

时间复杂度分析

  • 时间复杂度

    • 我们通过一个循环遍历整个数组,对于每个 end,最多需要移动 start 一次。每个元素最多被访问两次(一次是作为 end,一次是作为 start)。因此,时间复杂度为 O(n),其中 n 是数组的长度。
  • 空间复杂度

    • 我们只使用了常数空间来存储变量 startmax_len,因此空间复杂度是 O(1)。

总结

这个问题可以通过滑动窗口方法高效地解决。通过两个指针控制子数组的左右边界,能够在 O(n) 时间内找到最长稳定子数组的长度,空间复杂度也非常低,适用于较大规模的输入数据。