845. 数组中的最长山脉
给出一个整数数组 A,返回最长 “山脉” 的长度。
如果不含有 “山脉” 则返回 0。
思路
很容易想到暴力解法的思路,遍历数组,然后开始中心扩展,左边需要严格递减,右边需要严格递增,注意到两边都需要扩展。
代码
class Solution {
public:
int longestMountain(vector<int>& A) {
int n = A.size();
if(n <= 2) {
return 0;
}
int ans = 0;
for(int i = 1; i < n - 1; i++) {
//左边扩展
int left = i - 1;
while(left >= 0 && A[left] < A[left + 1]) {
left--;
}
//右边扩展
int right = i + 1;
while(right < n && A[right - 1] > A[right]) {
right++;
}
//左右边任一不扩展都不行
if(left == i - 1 || right == i + 1) {
continue;
}
ans = max(ans, right - left - 1);
}
return ans;
}
};
动态规划
容易想到暴力解法需要每次都枚举左右边界,定义left_max[i]表示从位置i开始可以向左边扩展的值,状态转移方程为left_max[i] = num[i] > num[i - 1]? left_max[i - 1] + 1 : 0,同理right_max[i]表示从位置i开始可以向右边扩展的值,状态转移方程为right_max[i] = num[i] > num[i + 1]? right_max[i + 1] + 1 : 0,边界条件left_max[0] = right_max[n - 1] = 0。
代码
class Solution {
public:
int longestMountain(vector<int>& A) {
int n = A.size();
if(n == 0) {
return 0;
}
vector<int> left(n, 0);
for(int i = 1; i < n; i++) {
left[i] = A[i] > A[i - 1]? left[i - 1] + 1 : 0;
}
vector<int> right(n, 0);
for(int i = n - 2; i >= 0; i--) {
right[i] = A[i] > A[i + 1]? right[i + 1] + 1 : 0;
}
int ans = 0;
for(int i = 1; i < n - 1; i++) {
if(left[i] != 0 && right[i] != 0) {
ans = max(ans, right[i] + left[i] + 1);
}
}
return ans;
}
};