To suffer without complaining is the only lesson that has to be learned in this life.
默默承受,是人生唯一必须懂得的道理。
问题描述
来源:LeetCode第845题
难度:中等
我们把数组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
解法一
山脉数组就是数组的前部分都是上升的,剩下的部分都是下降的,这样的数组称为山脉数组,之前专门讲过山脉数组,具体可以看下475,有效的山脉数组。
这里我们先找到上升的数组元素个数,到最高点之后再找下降的元素个数,他们相加再加上最顶端的元素个数(1)就是山脉数组的长度,我们只需要保留最长的即可。这里就以示例一为例来画个图看一下
来看下代码
1public int longestMountain(int[] A) {
2 int length = A.length;
3 int max = 0;//保存最长的山脉长度
4 int index = 1;
5 while (index < length) {
6 int up = 0;//上升的个数
7 int down = 0;//下降的个数
8
9 //既不上升也不下降的要过滤掉
10 while (index < length && A[index - 1] == A[index])
11 index++;
12 //统计上升的个数
13 while (index < length && A[index - 1] < A[index]) {
14 index++;
15 up++;
16 }
17 //统计下降的个数
18 while (index < length && A[index - 1] > A[index]) {
19 index++;
20 down++;
21 }
22 //上升和下降的个数必须都大于0,才能称为山脉,计算山脉的长度,
23 //保留最大的即可
24 if (up > 0 && down > 0)
25 max = Math.max(max, up + down + 1);
26 }
27 return max;
28}
其实我们还可以提前计算好每一个元素左边上升的个数和右边下降的个数,如果某个元素左边是上升的并且右边是下降的,那么这个元素就是山脉数组中最大的元素,也就是山顶,我们需要计算这个山脉数组的长度。如下图所示
来看下代码。
1public int longestMountain(int[] A) {
2 int length = A.length;
3 //up表示上升元素的个数
4 int[] up = new int[length];
5 for (int i = 1; i < length; i++) {
6 if (A[i] > A[i - 1])
7 up[i] = up[i - 1] + 1;
8 }
9 //down表示下降元素的个数
10 int[] down = new int[length];
11 for (int i = length - 1; i > 0; i--) {
12 if (A[i - 1] > A[i])
13 down[i - 1] = down[i] + 1;
14 }
15 //保留最大的长度
16 int max = 0;
17 for (int i = 0; i < length; i++) {
18 if (up[i] == 0 || down[i] == 0)
19 continue;
20 max = Math.max(max, up[i] + down[i] + 1);
21 }
22 return max;
23}
或者还可以合并一起,这样代码就越来越简洁了。
1public int longestMountain(int[] A) {
2 int max = 0, up = 0, down = 0;
3 for (int i = 1; i < A.length; ++i) {
4 //到山脚的拐点了,或者既没有上升也没有下降,把up和down
5 //重新赋值
6 if (down > 0 && A[i - 1] < A[i] || A[i - 1] == A[i])
7 up = down = 0;
8 //计算上升的长度
9 if (A[i - 1] < A[i])
10 up++;
11 //计算下降的长度
12 if (A[i - 1] > A[i])
13 down++;
14 //既有上升又有下降,说明是山脉数组,他是他的长度,
15 //保留最长的即可
16 if (up > 0 && down > 0)
17 max = Math.max(max, up + down + 1);
18 }
19 return max;
20}