LeetCode 845. 数组中的最长山脉
https://leetcode-cn.com/problems/longest-mountain-in-array/
难度:中等
我们把数组 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
解法1:状态判断
根据题意,我们需要寻找数组中的最长山脉,而这条山脉一定会是连续的,因此我们可以找到一种方案只遍历一次数组,计算每条山脉的长度,并从中选取最长的山脉。
对于数组中的数字 A[i]
(0 <= i < length - 1
),它只有三种状态:
- 状态1:当前数字小于下一数字:
A[i] < A[i+1]
,这种情况,它可能会是一条山脉的左半组成部分 - 状态2:当前数字等于下一数字:
A[i] == A[i+1]
,这种情况,这个数字可能会是山脉的右半部分的结束位置,也有可能不属于山脉的一部分 - 状态3:当前数字大于下一数字:
A[i] > A[i+1]
,这种情况,这个数字可能会是一条山脉的右半组成部分
且要构成一条山脉,需要先增后减,我们可以定义一个 temp
来表示组成一个山脉的数字个数,初始为 0
,当遇到状态1和状态3时,temp
都会加 1
,再定义一个 decrease
来标识对于一串连续的数字,是否出现了递减的部分。
注意到,一条山脉只会在遇到以下三种情况时结束:
- 结束1:当前数字处于递减状态(状态1)且遇到数组末尾
- 结束2:前面数字是处于递减状态(状态3),而当前数字处于递增状态(状态1)
- 结束3:前面数字处于递减状态(状态3),当前数字处于平缓状态(状态2)
具体操作可结合代码和注释来理解
C代码如下:
int longestMountain(int* A, int ASize){
if (ASize < 3) {
return 0;
}
bool decrease = false;
int i, max = 0, temp = 0;
for (i = 0; i < ASize-1; i++) {
// 若处于递增状态
if (A[i + 1] > A[i]) {
// 结束情况2:前面数字处于递减状态,而当前处于递增状态
if (decrease) {
decrease = false;
max = fmax(max, temp + 1); // 算上当前的数字: temp + 1
temp = 0;
}
temp++;
} else if (A[i + 1] == A[i]) {
// 结束情况2:前面数字处于递减状态,当前数字处于平缓状态
if (decrease) {
decrease = false;
max = fmax(max, temp + 1);
}
temp = 0;
} else if (temp > 0){
decrease = true;
temp++;
// 结束情况1:当前数字处于递减状态,而遇到了数组末尾
if (i == ASize - 2) {
max = fmax(max, temp + 1);
}
}
}
return max;
}
解法2:动态规划
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!