1、题目描述
我们把数组 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。)
输入:[2,1,4,7,3,2,5]
输出:5
解释:最长的 “山脉” 是 [1,4,7,3,2],长度为 5。
输入:[2,2,2]
输出:0
解释:不含 “山脉”。
2、代码详解
data_list = [1,3,6,7,6,8,2,4,2,1]
def longest_mountain(data_array):
n = len(data_array)
if n <= 2:
return 0
length_max = 0
i = 1 # 左边界从1也就是第二个元素开始遍历
while i < n-1: # 右边界
if data_array[i-1] < data_array[i] and data_array[i] > data_array[i+1]: # 例如: 1< 3 >2
left = i - 1
right = i + 1 # 以i为山顶的右山底
while left > 0 and data_array[left-1] < data_array[left]: # 向左找山底
left -= 1
while right < n-1 and data_array[right+1] < data_array[right]: # 向右找山底
right += 1
length_max = max(length_max, (right-left+1))
i = right # 指针 移动到右边不满足条件的位置
else:
i += 1 # 移动左边界
return length_max
# 枚举山顶
def longest_mountain_v1(data_array):
'''
: 遍历每个元素 找到向左边能延申的最长长度 找到向右边能延申的最长长度 左边+右边+本身(1)就是最长的长度 最后求最大值
: 左侧山脚到山顶的序列是严格单调递增的,而从山顶到右侧山脚的序列是严格单调递减
'''
if not data_array:
return 0
n = len(data_array)
left = [0] * n
for i in range(1, n):
left[i] = (left[i - 1] + 1 if data_array[i - 1] < data_array[i] else 0) # 向右遍历 递增则当前可延申的长度为前一个+1,否则为0
right = [0] * n
for i in range(n - 2, -1, -1):
right[i] = (right[i + 1] + 1 if data_array[i + 1] < data_array[i] else 0) # 向左遍历 递减则当前可延申的长度为前一个+1,否则为0
ans = 0
for i in range(n):
if left[i] > 0 and right[i] > 0:
ans = max(ans, left[i] + right[i] + 1)
return ans
print(longest_mountain(data_list))
print(longest_mountain_v1(data_list))