一、前言
人只能活一回,梦想却有无数个,唯有放手一搏,才能知道机会属不属于自己。
每天五分钟,看懂一道简单、中等难度的算法题,尽可能将复杂的题讲清楚。
疯狂学习python中,2020-10-25更新
二、题目
我们把数组 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
解释:不含 “山脉”。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-mountain-in-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
三、解法和思路
1、思考步骤
- 对于一个数组组成的山脉, 一定满足 B[i-1] < B[i] > B[B.length - 1] B[i]是山顶最高值,B[i-1]则是一个单调递增的区间, B[B.length-1]是一个单调递减的区间
- 我们从列表A首元素开始找,当找到前i个元素都是递增时,且i的长度 >=2 ,说明找到了左侧山脉
- 我们从列表A逆序查找,当找到i个元素都是递增时,且i的长度>=2 ,说明找到右侧山峰
- 通过遍历数组A,如果左侧山脉与右侧山脉基于某一点重合,则说明找到了一条山脉。
可以设置一个值记录山脉长度,然后将多个山脉进行长度比较,返回最长的那个值。
1、思考左侧边界问题
我们用left[i]来表示左侧最多能拓展的元素个数
如果 A[i−1] < A[i] ,意味着能拓展向左拓展更多一位元素,那么有公式
left[i] = left[i-1] +1
如果 A[i-1] > A[i]
left[i] = 0
当 i=0 时,A[i] 为首元素,无法向左扩展,因此同样有
left[0] = 0
2、 思考右侧边界问题
我们用right[i]来表示左侧最多能拓展的元素个数
如果A[i+1] < A[i],意味着能向右拓展一个元素,那么由公式
right[i] = right[i+1] +1
如果A[i+1] > A[i]
right[i] = 0
3、 思考山脉合并问题
当我们得到所有的left[]以及right[]的时候,就可以通过遍历列举出山顶了
只有当left[i]和left[i]均大于0的时候,A[i]才能作为山顶
四、代码实例
from typing import List
class Solution:
def longestMountain(self, A: List[int]) -> int:
if not A:
return 0
n = len(A)
# 左侧山脉
left = [0] * n
for i in range(1, n):
left[i] = (left[i-1]+1 if A[i] > A[i-1] else 0)
# 右侧山脉
right = [0] * n
for i in range(n-2, -1, -1):
right[i] = (right[i+1]+1 if A[i+1] < A[i] else 0)
# 记录山脉长度
ans = 0
for i in range(n):
if left[i] > 0 and right[i] > 0:
ans = max(ans, left[i]+right[i]+1)
print(ans)
return ans
if __name__ == '__main__':
A = [2, 1, 4, 7, 3, 2, 5]
obj = Solution()
obj.longestMountain(A)