问题描述
小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。
- 我们需要找出最长的连续子数组,满足上述条件。
-
滑动窗口/双指针思路:
- 我们可以使用滑动窗口的技巧,通过一个指针遍历整个数组,保持一个区间 [start, end],其中
a[start]到a[end]是一个稳定的子数组。 - 如果当前元素
a[end]和前一个元素a[end-1]之间的差的绝对值大于 1,说明这个子数组不稳定,需要调整窗口的起始位置start。 - 每次遍历时记录当前稳定子数组的长度,最终输出最大的稳定子数组长度。
- 我们可以使用滑动窗口的技巧,通过一个指针遍历整个数组,保持一个区间 [start, end],其中
-
具体步骤:
-
使用两个指针:
start和end,初始化时都指向数组的第一个元素。 -
维护一个变量
max_len来记录当前找到的最长稳定子数组的长度。 -
遍历数组,对于每一个新元素
a[end]:- 如果
|a[end] - a[end-1]| > 1,说明从start到end的子数组不稳定,需要移动start指针,直到a[start]到a[end]之间满足稳定条件。 - 如果是稳定的,则继续扩大
end指针,并更新max_len。
- 如果
-
-
边界条件:
- 如果数组长度为 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
解释
-
初始化:
start为子数组的起始位置,初始值为 0。max_len用于记录最长稳定子数组的长度,初始化为 1,因为单个元素子数组至少是稳定的。
-
滑动窗口逻辑:
end从 1 开始遍历数组,表示当前的右边界。- 对于每个
end,检查|a[end] - a[end-1]|是否大于 1。如果大于 1,说明从start到end的子数组不稳定,需要移动start,直到区间[start, end]是稳定的。 - 每次移动
end时,更新max_len,确保记录最大长度。
-
返回值:
- 最后返回
max_len,即最长稳定子数组的长度。
- 最后返回
时间复杂度分析
-
时间复杂度:
- 我们通过一个循环遍历整个数组,对于每个
end,最多需要移动start一次。每个元素最多被访问两次(一次是作为end,一次是作为start)。因此,时间复杂度为 O(n),其中 n 是数组的长度。
- 我们通过一个循环遍历整个数组,对于每个
-
空间复杂度:
- 我们只使用了常数空间来存储变量
start、max_len,因此空间复杂度是 O(1)。
- 我们只使用了常数空间来存储变量
总结
这个问题可以通过滑动窗口方法高效地解决。通过两个指针控制子数组的左右边界,能够在 O(n) 时间内找到最长稳定子数组的长度,空间复杂度也非常低,适用于较大规模的输入数据。