区间动态规划例题:最长湍流子数组问题
字数 2380 2025-10-26 09:00:43
区间动态规划例题:最长湍流子数组问题
题目描述
给定一个整数数组 arr,如果某个子数组中元素的比较符号在相邻元素之间来回翻转(即 arr[i] > arr[i+1] < arr[i+2] > ... 或 arr[i] < arr[i+1] > arr[i+2] < ...),则称该子数组为湍流子数组。要求返回 arr 中最长湍流子数组的长度。
例如:
- 输入:
arr = [9,4,2,10,7,8,8,1,9]
输出:5
解释:最长湍流子数组为[4,2,10,7,8],对应比较符号为< > < >。 - 输入:
arr = [4,8,12,16]
输出:2
解释:相邻元素比较符号相同(均为<),因此最长湍流子数组长度为2(例如[4,8])。
解题思路
本题可通过区间动态规划或状态机动态规划求解。这里采用区间动态规划的思路,定义 dp[i][j] 表示子数组 arr[i...j] 是否为湍流子数组,但直接二维 DP 会超时。更高效的方法是线性 DP,记录以每个位置结尾的最长湍流子数组长度。
步骤分解
-
状态定义
设up[i]表示以i结尾且最后一段比较为arr[i-1] < arr[i]的最长湍流子数组长度。
设down[i]表示以i结尾且最后一段比较为arr[i-1] > arr[i]的最长湍流子数组长度。 -
状态转移
- 若
arr[i-1] < arr[i]:up[i] = down[i-1] + 1(前一段必须是下降趋势,现在转为上升)down[i] = 1(下降趋势中断,重新开始)
- 若
arr[i-1] > arr[i]:down[i] = up[i-1] + 1(前一段必须是上升趋势,现在转为下降)up[i] = 1(上升趋势中断,重新开始)
- 若
arr[i-1] == arr[i]:up[i] = down[i] = 1(相等时趋势中断,长度重置为 1)
- 若
-
初始化
所有位置初始长度均为1(单个元素可视为湍流子数组)。 -
结果计算
遍历过程中记录max(up[i], down[i])的最大值。
示例推导
以 arr = [9,4,2,10,7,8,8,1,9] 为例:
| i | arr[i] | up[i] | down[i] | 说明 |
|---|---|---|---|---|
| 0 | 9 | 1 | 1 | 初始化 |
| 1 | 4 | 1 | 2 | 9>4,下降趋势延续(down[1]=up[0]+1=2) |
| 2 | 2 | 1 | 3 | 4>2,下降趋势延续(down[2]=up[1]+1=2?注意:连续下降不符合交替,应重置?) |
修正:需严格交替,因此:
- 当
arr[i-1] > arr[i]时,若前一段是下降趋势(即arr[i-2] > arr[i-1]),则不能直接延续,而应重置为2。但通过up[i]和down[i]的定义可自动处理:down[i]依赖up[i-1],即前一段必须是上升趋势才能延续。
正确推导:
| i | arr[i] | 比较关系 | up[i] | down[i] | 解释 |
|---|---|---|---|---|---|
| 0 | 9 | - | 1 | 1 | 初始化 |
| 1 | 4 | 9>4 (>) | 1 | 2 | down[1]=up[0]+1=2 |
| 2 | 2 | 4>2 (>) | 1 | 1 | 前一段是下降,当前仍下降,重置 down[2]=1 |
| 3 | 10 | 2<10 (<) | 2 | 1 | up[3]=down[2]+1=2 |
| 4 | 7 | 10>7 (>) | 1 | 3 | down[4]=up[3]+1=3 |
| 5 | 8 | 7<8 (<) | 4 | 1 | up[5]=down[4]+1=4 |
| 6 | 8 | 8=8 (=) | 1 | 1 | 相等重置 |
| 7 | 1 | 8>1 (>) | 1 | 2 | down[7]=up[6]+1=2 |
| 8 | 9 | 1<9 (<) | 3 | 1 | up[8]=down[7]+1=3 |
最大值在 i=5 时取得 max(4,1)=5(实际长度为 5,对应子数组 [4,2,10,7,8],索引 1~5)。
复杂度分析
- 时间复杂度:O(n),遍历一次数组。
- 空间复杂度:O(n),可优化至 O(1)(仅需保存前一个状态)。
代码实现(Python)
def maxTurbulenceSize(arr):
n = len(arr)
up, down = 1, 1
res = 1
for i in range(1, n):
if arr[i] > arr[i-1]:
up = down + 1
down = 1
elif arr[i] < arr[i-1]:
down = up + 1
up = 1
else:
up = down = 1
res = max(res, up, down)
return res
总结
本题通过定义 up 和 down 状态,利用动态规划记录以每个位置结尾的最长湍流子数组长度,通过比较相邻元素的大小关系切换状态,最终得到全局最大值。