941. 有效的山脉数组
题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/valid-mountain-array/
题目
给定一个整数数组 A
,如果它是有效的山脉数组就返回 true
,否则返回 false
。
让我们回顾一下,如果 A 满足下述条件,那么它是一个山脉数组:
A.length >= 3
- 在
0 < i < A.length - 1
条件下,存在i
使得:A[0] < A[1] < ... A[i-1] < A[i]
A[i] > A[i+1] > ... > A[A.length - 1]
示例 1:
输入:[2,1]
输出:false
示例 2:
输入:[3,5,5]
输出:false
示例 3:
输入:[0,3,2,1]
输出:true
提示:
0 <= A.length <= 10000
0 <= A[i] <= 10000
解题思路
思路:双指针
如果有兴趣的话,解决这道题之后可以尝试下站内 845. 数组中的最长山脉。
看回本题,本题中要求给定的整数数组是否是有效的山脉数组。
题目给出的符合山脉数组的条件:
- 数组长度至少为 3;
- 存在
i
(其中0 < i < A.length-1
),使得:A[0...i-1]
严格小于A[i]
;A[i]
严格大于A[i+1...A.length-1]
。
结合前面的图来看,注意,A[0...i]
这部分一定是严格单调递增;而 A[i...A.length-1]
一定是严格单调递减的,不能存在相等的情况。
那么,这里我们可以定义双指针,从数组的首尾两端往中间聚拢,寻找峰顶。
具体的做法如下:
- 定义双指针 left、right,初始指向数组的首尾两端;
- 先处理 left 指针,当满足右边的值严格大于当前值(即 left 指向的值)时,left 往右边移动,循环直至不符合条件;
- 再处理 right 指针,当满足左边的值严格大于当前值(这里是 right 指向的值)时,right 往左边移动,循环直至不符合条件;
- 最终判断,left 指针与right 指针是否重合。若重合,表示当前位置即是峰顶,数组为山脉数组;否则不是。
这里需要注意 i
(其中 0 < i < A.length-1
)是不能够在数组两端的。
具体的代码实现如下。
class Solution:
def validMountainArray(self, A: List[int]) -> bool:
n = len(A)
# 定义指针
left = 0
right = n - 1
# 先处理 left 指针
# 满足右边的值大于当前值时,往右移动
# 注意边界
while left + 1 < n and A[left] < A[left+1]:
left += 1
# 处理 right 指针
# 满足左边的值大于当前值时,往左移动,同样注意边界问题
while right - 1 > 0 and A[right - 1] > A[right]:
right -= 1
# 判断 left 指针是否与 right 指针重合
# 同时注意,峰顶不能在数组两端
if left > 0 and right < n - 1 and left == right:
return True
return False
复杂度分析
- 时间复杂度: O ( N ) O(N) O(N), N N N 表示给定数组的长度。
- 空间复杂度: O ( 1 ) O(1) O(1),仅定义指针。
欢迎关注
公众号 【书所集录】
如有错误,烦请指正,欢迎指点交流。