持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
一、题目
LeetCode 数组中的最长山脉
把符合下列属性的数组 arr 称为 山脉数组 :
arr.length >= 3 存在下标 i(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 。
示例 1:
输入:arr = [2,1,4,7,3,2,5]
输出:5
解释:最长的山脉子数组是 [1,4,7,3,2],长度为 5。
示例 2:*
输入:arr = [2,2,2]
输出:0
解释:不存在山脉子数组。
提示:*
1 <= arr.length <= 104
0 <= arr[i] <= 104
二、题解
方法一
山脉数组就像是数组元素值连起来像山一样的,山脉数组中中间那个值就是数组中最大的值为山顶元素,山顶元素往左方向是严格递减的,同样的山顶元素往右方向也是严格递减的,对此我们可以先找到山顶元素,然后再往两边递推就可以了。首先可以定义一个同等大小的数组left,那么left[i]就表示以arr[i]为山顶元素时往左递推符合递减的元素数量;同样的定义一个同等大小的数组right,那么right[i]就表示以arr[i]为山顶元素时往右递推符合递减的元素数量。初始的left[0]时arr[0]数组左边无元素所以为0,同样的right[len - 1]时arr[len - 1]数组右边无元素也为0。然后先从左到右遍历arr数组元素,以每一个元素arr[i]为山顶元素,如果arr[i - 1] < arr[i]则是符合递减的,所以arr[i]就可以添加一个元素长度即left[i] = left[i - 1] + 1;否则不符合递减就无法组成山脉数组即left[i] = 0。再然后从右到左遍历arr数组元素,以每一个元素arr[i]为山顶元素,如果arr[i] > arr[i + 1]是符合递减的,所以arr[i]就可以添加一个元素长度即right[i] = right[i + 1] + 1;否则不符合递减就无法组成山脉数组即right[i] = 0。最后遍历left、right两个数组,计算以arr[i]为山顶元素时山脉数组的长度,只有当left[i] > 0 && right[i] > 0时才能组成山脉数组,最后保存最长的山脉数组的长度返回。
三、代码
方法一 Java代码
class Solution {
public int longestMountain(int[] arr) {
int len = arr.length;
int[] left = new int[len];
for (int i = 1; i < len; i++) {
if (arr[i - 1] < arr[i]) {
left[i] = left[i - 1] + 1;
}
}
int[] right = new int[len];
for (int i = len - 2; i >= 0; i--) {
if (arr[i] > arr[i + 1]) {
right[i] = right[i + 1] + 1;
}
}
int mountain = 0;
for (int i = 0; i < len; ++i) {
if (left[i] > 0 && right[i] > 0) {
mountain = Math.max(mountain, left[i] + right[i] + 1);
}
}
return mountain;
}
}
时间复杂度:O(n),需要遍历两次数组元素计算山脉左右两边元素,最后再遍历一次枚举山顶元素计算左右两边长度。
空间复杂度:O(n),需要使用两个同等大小的数组。