题目描述
思路解析动画文字版
记住这套「升就 up 接旧 down、降就 down 接旧 up、相等全归 1,每步刷新答案」,下面每一帧都在套它。
开局:第 0 个元素 9 自己就是一段长度 1 的湍流段(绿色)。up 和 down 都初始化成 1,从第 1 个起才有「前一个」可比。
扫到第 1 个 4,和前一个 9 比。绿色是到上一个为止还在生长的湍流段(长度 1),此刻 up=1、down=1。看着是下降,下一帧看 down 怎么接。
4 比 9 小,这一步是下降。反过来,新的 down 接在「上一个结尾是上升」的段后面:down = 旧 up + 1 = 2;up 归 1。刷新答案 ans=2。
扫到第 2 个 2,和前一个 4 比。绿色是到上一个为止还在生长的湍流段(长度 2),此刻 up=1、down=2。看着是下降,下一帧看 down 怎么接。
2 比 4 小,这一步是下降。反过来,新的 down 接在「上一个结尾是上升」的段后面:down = 旧 up + 1 = 2;up 归 1。还没超过 ans=2,答案不动。
扫到第 3 个 10,和前一个 2 比。绿色是到上一个为止还在生长的湍流段(长度 2),此刻 up=1、down=2。看着是上升,下一帧看 up 怎么接。
10 比 2 大,这一步是上升。湍流要交替,所以新的 up 接在「上一个结尾是下降」的段后面:up = 旧 down + 1 = 3;同向接不上的 down 归 1。这个 3 比旧答案大,刷新 ans=3。
扫到第 4 个 7,和前一个 10 比。绿色是到上一个为止还在生长的湍流段(长度 3),此刻 up=3、down=1。看着是下降,下一帧看 down 怎么接。
7 比 10 小,这一步是下降。反过来,新的 down 接在「上一个结尾是上升」的段后面:down = 旧 up + 1 = 4;up 归 1。刷新答案 ans=4。
扫到第 5 个 8,和前一个 7 比。绿色是到上一个为止还在生长的湍流段(长度 4),此刻 up=1、down=4。看着是上升,下一帧看 up 怎么接。
8 比 7 大,这一步是上升。湍流要交替,所以新的 up 接在「上一个结尾是下降」的段后面:up = 旧 down + 1 = 5;同向接不上的 down 归 1。这个 5 比旧答案大,刷新 ans=5。
扫到第 6 个 8,和前一个 8 比。绿色是到上一个为止还在生长的湍流段(长度 5),此刻 up=5、down=1。两个数一样大,怕是要断,下一帧见分晓。
8 和 8 一样大,既不算上升也不算下降,湍流彻底断在这里。up 和 down 同时归 1,从第 6 个重新数。注意 ans 仍保留着 5,断开只清空当前段,绝不抹掉历史最长。
扫到第 7 个 1,和前一个 8 比。绿色是到上一个为止还在生长的湍流段(长度 1),此刻 up=1、down=1。看着是下降,下一帧看 down 怎么接。
1 比 8 小,这一步是下降。反过来,新的 down 接在「上一个结尾是上升」的段后面:down = 旧 up + 1 = 2;up 归 1。还没超过 ans=5,答案不动。
全部扫完。一路上 up 和 down 此消彼长,最长的一段湍流是高亮的这 5 个:4、2、10、7、8,比较符大、小、大、小完整交替。后面 8、8 相等把湍流打断,所以没能更长。答案 5。
回放这段赢家,看比较符怎么一步步翻转。先单看第 1 个 4,长度 1。
4 到 2 是下降,比较符是「大」,和前一对正式开头,交替成立,长度到 2。
2 到 10 是上升,比较符是「小」,和前一对正好相反,交替成立,长度到 3。
10 到 7 是下降,比较符是「大」,和前一对正好相反,交替成立,长度到 4。
7 到 8 是上升,比较符是「小」,和前一对正好相反,交替成立,长度到 5。比较符一路 大、小、大、小 交替,五个元素,答案就是 5。
边界先想清:单元素为 1、单调或全相等都退化成最多 2 或 1。
两个高频追问,重点是「为什么要双状态」。
参考代码
from __future__ import annotationsfrom typing import *from collections import *from functools import *from itertools import *from math import *from heapq import *from bisect import *class Solution: def maxTurbulenceSize(self, arr: List[int]) -> int: ans = f = g = 1 for a, b in pairwise(arr): ff = g + 1 if a < b else 1 gg = f + 1 if a > b else 1 f, g = ff, gg ans = max(ans, f, g) return ans复杂度
- 时间:O(n),从头到尾扫一遍,每个元素只看一次
- 空间:O(1),只用 up、down、ans 三个变量,状态滚动复用
易错点
面试追问把动画讲成自己的话
追问这题和「最长连续递增子数组」(LC674)有什么区别?
追问为什么非要两个状态,一个变量行不行?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
最低票价
LeetCode 983 · 中等 · 沿着 动态规划套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题