题目描述
思路解析动画文字版
记住「先找峰顶(两边都比它矮),再向左右扩展量长度」,下面每帧都在套它。
看 i=1(值 1)是不是峰顶:左边 2 < 1 就不成立,不是峰顶,i 前进一格。
看 i=2(值 4)是不是峰顶:左边 1 < 4 成立,但右边 4 > 7 不成立,不是峰顶,i 前进一格。
i=3(值 7)左边 4 更小、右边 6 也更小,是个峰顶(绿色)!接下来向左右扩展看这座山有多长。
向左走:4 < 7,左边还在严格上升,左边界 l 移到 2,绿色山脉向左长一格。
向左走:1 < 4,左边还在严格上升,左边界 l 移到 1,绿色山脉向左长一格。
向右走:7 > 6,右边还在严格下降,右边界 r 移到 4,绿色山脉向右长一格。
向右走:6 > 3,右边还在严格下降,右边界 r 移到 5,绿色山脉向右长一格。
这座山脉从下标 1 到 5,长度 5。比之前的最长还长,刷新答案为 5。
关键一步:这座山下降坡上的点不可能再是别的峰顶,所以把 i 直接跳到右端 5,下一轮从 6 开始——这正是代码里的 i=r,也是整体保持线性 O(n) 的原因。
看 i=6(值 5)是不是峰顶:左边 3 < 5 成立,但右边 5 > 8 不成立,不是峰顶,i 前进一格。
看 i=7(值 8)是不是峰顶:左边 5 < 8 成立,但右边 8 > 9 不成立,不是峰顶,i 前进一格。
i=8(值 9)左边 8 更小、右边 2 也更小,是个峰顶(绿色)!接下来向左右扩展看这座山有多长。
向左走:8 < 9,左边还在严格上升,左边界 l 移到 7,绿色山脉向左长一格。
向左走:5 < 8,左边还在严格上升,左边界 l 移到 6,绿色山脉向左长一格。
向左走:3 < 5,左边还在严格上升,左边界 l 移到 5,绿色山脉向左长一格。
向右走:9 > 2,右边还在严格下降,右边界 r 移到 9,绿色山脉向右长一格。
向右走:2 > 1,右边还在严格下降,右边界 r 移到 10,绿色山脉向右长一格。
这座山脉从下标 5 到 10,长度 6。比之前的最长还长,刷新答案为 6。
关键一步:这座山下降坡上的点不可能再是别的峰顶,所以把 i 直接跳到右端 10,下一轮从 11 开始——这正是代码里的 i=r,也是整体保持线性 O(n) 的原因。
扫完所有峰顶,最长的一座山脉是绿色这 6 个(3→5→8→9→2→1):从 3 一路严格升到峰顶,再严格降到 1。答案 6。
边界先想清:空、单调、最短山脉(长度 3)。
面试常追问另一种 up/down 计数解法与「为什么最短是 3」。
参考代码
from typing import Listclass Solution: def longestMountain(self, arr: List[int]) -> int: n = len(arr) ans = 0 i = 1 while i < n - 1: if arr[i - 1] < arr[i] > arr[i + 1]: l = r = i while l > 0 and arr[l - 1] < arr[l]: l -= 1 while r + 1 < n and arr[r] > arr[r + 1]: r += 1 ans = max(ans, r - l + 1) i = r i += 1 return ans复杂度
- 时间:O(n),下降坡不反复当峰顶,各点常数次触碰
- 空间:O(1),只用几个下标变量
易错点
面试追问把动画讲成自己的话
追问除了「枚举峰顶 + 扩展」,还有别的线性解吗?
追问为什么山脉最短是 3?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
满足条件的子序列数目
LeetCode 1498 · 中等 · 沿着 双指针套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题