题目描述
我们把数组 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
遍历山顶
时间复杂度 O(n*2)
注意边界处理
class Solution {
public int longestMountain(int[] A) {
int len = A.length;
if(len <3) return 0;
int res = 0;
//遍历每个节点 把每个节点当山顶
for(int i=1;i<len-1;i++){
int count=0;
if(A[i-1]<A[i] && A[i]>A[i+1]){
count = 3;
int p1 = i-1;
int p2 = i+1;
while(p1>0 && A[p1 -1]< A[p1]){
p1--;
count++;
}
while(p2<len-1 && A[p2]> A[p2+1] ){
p2++;
count++;
}
}
res = Math.max(res,count);
}
return res;
}
}
动态规划
时间复杂度 O(n)
一次遍历
public int longestMountain(int[] A) {
if(A.length < 3)return 0;
final int n = A.length;
int ans = 0;
//一次遍历 用mode来标记是上升还是下降 最符合人脑的思维方式
int prev = A[0];//初始prev为A[0]
int start = 0;//一个有效“山脉”的开始位置
int mode = 0;//0-开始,1-已进入up序列 2-已进入down序列
for (int i = 1; i < n; i++) {
if(mode==0) {
if(A[i] > prev) {
mode = 1;
start = i-1;
}
} else if(mode == 1) {
if(A[i] < prev) {
mode = 2;
} else if(A[i] == prev) {
mode = 0;
}
} else {
if(A[i] > prev) {
mode = 1;
start = i-1;
} else if(A[i] == prev) {
mode = 0;
}
}
// 收集一次答案
if(mode==2) {
ans = Math.max(ans, i-start+1);
}
prev = A[i];
}
return ans;
}
遍历山顶2
class Solution {
public int longestMountain(int[] A) {
int n = A.length;
if (n == 0) {
return 0;
}
// 两个数组 left和right 分别代表递增的left的最高点(山顶) 和递减的right最高点(另一个山顶)
// 最后的最长山脉就是left-right+1
int[] left = new int[n];
for (int i = 1; i < n; ++i) {
left[i] = A[i - 1] < A[i] ? left[i - 1] + 1 : 0;
}
int[] right = new int[n];
for (int i = n - 2; i >= 0; --i) {
right[i] = A[i + 1] < A[i] ? right[i + 1] + 1 : 0;
}
int ans = 0;
for (int i = 0; i < n; ++i) {
if (left[i] > 0 && right[i] > 0) {
ans = Math.max(ans, left[i] + right[i] + 1);
}
}
return ans;
}
}
遍历山脚
class Solution {
public int longestMountain(int[] A) {
int n = A.length;
int ans = 0;
int left = 0;
while (left + 2 < n) {
int right = left + 1;
if (A[left] < A[left + 1]) {
while (right + 1 < n && A[right] < A[right + 1]) {
++right;
}
if (right < n - 1 && A[right] > A[right + 1]) {
while (right + 1 < n && A[right] > A[right + 1]) {
++right;
}
ans = Math.max(ans, right - left + 1);
} else {
++right;
}
}
left = right;
}
return ans;
}
}