我们把数组 A 中符合下列属性的任意连续子数组 B 称为 “山脉”:
B.length >= 3
- 存在
0 < i < B.length - 1
使得B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1]
(注意:B
可以是A
的任意子数组,包括整个数组A
。)
给出一个整数数组 A
,返回最长 “山脉” 的长度。
如果不含有 “山脉” 则返回 0。
示例 1:
输入:[2,1,4,7,3,2,5]
输出:5
解释:最长的 “山脉” 是 [1,4,7,3,2],长度为 5。
示例 2:
输入:[2,2,2]
输出:0
解释:不含 “山脉”。
提示:
- 0 <= A.length <= 10000
- 0 <= A[i] <= 10000
解答
模拟,从头到尾遍历:
class Solution {
public:
int longestMountain(vector<int>& A) {
int len = A.size();
if(len < 3)
return 0;
int left, cur, right, result;
left = cur = right = result = 0;
// 去除开头的下降序列
while(cur < len - 1 && A[cur] >= A[cur+1])
cur++;
while(cur < len - 1){
left = cur;
// 单调上升
while(cur < len - 1 && A[cur] < A[cur+1]){
cur++;
}
// 单调下降
while(cur < len - 1 && A[cur] > A[cur+1]){
cur++;
}
// 确保既经历了上升,又经历了下降
if(A[cur] < A[cur-1]){
right = cur;
result = max(result, right - left + 1);
}
// 去除再峰顶或谷底出现连续相同值的情况
while(cur < len - 1 && A[cur] >= A[cur+1]){
cur++;
}
}
return result;
}
};
中心扩展法:
class Solution {
public:
int longestMountain(vector<int>& A) {
int len = A.size();
if(len < 3)
return 0;
int result = 0;
for(int cur = 1; cur < len - 1; cur++){
// 找到比左右两端都大的点
if(A[cur-1] < A[cur] && A[cur+1] < A[cur]){
int left = cur - 1;
int right = cur + 1;
while(left > 0 && A[left - 1] < A[left])
left--;
while(right < len - 1 && A[right+1] < A[right])
right++;
result = max(result, right - left + 1);
}
}
return result;
}
};