[Leetcode解題] 845. Longest Mountain in Array
8 February 2025
medium
two-pointer
題目
845. Longest Mountain in Array 一個數列如果滿足 山脈數列 (mountain array)的條件,需要滿足下列條件:
- 數列長度至少是 3:
arr.length >= 3
- 存在一個索引
i
(以 0 為基準,0 < i < arr.length - 1
),使得:arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
現在,給你一個數列 arr
,請返回最長山脈子數列的長度。如果沒有山脈子數列,則返回 0
。
解題思路
-
定義山脈條件 要構成一個合法的「山脈」,需要先遞增,然後在達到高峰後遞減。因此我們需要在陣列中找到符合此模式的子區間。
- 雙指針遍歷法
使用左右指針進行遍歷,其中:
l
指向目前正在考察的山脈的左邊界。dir
記錄方向,0 代表正在遞增,1 代表正在遞減。- 當前的區間長度則是右指針
r
與左指針l
的差值。
- **重置條件
在以下情況下需要重新重置左邊界指針
l
:- 當兩個相鄰元素相等時,無法構成山脈,直接重置。
- 當遞增段沒有接上遞減段時,則需要將左邊界移動到當前位置,繼續搜索。
- 更新最長山脈長度 在找到合法山脈區間後,更新最大長度。
Python 實作
class Solution:
def longestMountain(self, arr: list[int]) -> int:
l = 0 # 左邊界指針
dir = 0 # 方向 0: 遞增中, 1: 遞減中
max_len = 0 # 紀錄最長山脈長度
def reset(idx):
nonlocal l, dir
l = idx
dir = 0 # 重置方向為遞增
# 開始遍歷陣列
for r in range(1, len(arr)):
if arr[r] == arr[r - 1]: # 相鄰元素相等,無法構成山脈
reset(r)
elif l == r - 1 and arr[r] < arr[r - 1]: # 一開始就遞減,不算山脈
reset(r)
elif dir == 0 and arr[r] < arr[r - 1]: # 進入遞減段
dir = 1
elif dir == 1 and arr[r] > arr[r - 1]: # 遞減後又遞增,無法構成山脈
reset(r - 1)
if dir == 1: # 如果正在遞減段,計算山脈長度
max_len = max(max_len, r - l + 1)
return max_len
C++實作
class Solution {
public:
int longestMountain(vector<int>& arr) {
int l = 0;
int dir = 0; // 0 表示上升階段,1 表示下降階段
auto reset = [&](int idx) {
dir = 0; // 重置為上升階段
l = idx; // 更新左邊界
};
int len = 0;
for (int r = 1; r < arr.size(); r++) {
if (arr[r] == arr[r - 1]) // 平坦區域,重置起點
reset(r);
else if (l == r - 1 && arr[r] < arr[r - 1]) // 一開始就下降,重置
reset(r);
else if (dir == 0 && arr[r] < arr[r - 1]) // 開始下降
dir = 1;
else if (dir == 1 && arr[r] > arr[r - 1]) // 在下降後又上升,重置
reset(r - 1);
if (dir == 1) // 如果處於下降階段,計算山型長度
len = max(len, r - l + 1);
}
return len;
}
};
時間複雜度分析
- 時間複雜度:$O(n)$
- 每個元素僅被遍歷一次,因此時間複雜度為 $O(n)$,其中 $n$ 是陣列的長度。
- 空間複雜度:$O(1)$
- 只使用常數倍外空間來儲存變數,因此空間複雜度為$O(1)$。