题目:
Given an array of integers arr
, return true
if and only if it is a valid mountain array.
Recall that arr is a mountain array if and only if:
arr.length >= 3
- There exists some
i
with0 < i < arr.length - 1
such that:arr[0] < arr[1] < ... < arr[i - 1] < A[i]
arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
Example 1:
Input: arr = [2,1] Output: false
Example 2:
Input: arr = [3,5,5] Output: false
Example 3:
Input: arr = [0,3,2,1] Output: true
Constraints:
1 <= arr.length <= 10^4
0 <= arr[i] <= 10^4
思路1:
题意是找数组是不是一个山峰型的组,必须完整,半峰也返回false。作为一道easy题只有33%的通过率,不是很确定原因。正常思路是走一遍数组,只要一直上升就每次更新当前最高点的index,如果中途遇到了相等,则false。如果遇到下降,break出来。这里需要检查是不是半峰,如果最高点index是0,说明并没有上升,直接就下降了;如果最高点已经是数组的最后一个,那就是一直在上升,没有下降空间,这两种情况都直接false。然后就从当前最高点继续往下扫描,维持一直降的情况就好了。这是我做的比较直白的方法,思路2中介绍Lee神Lee215的逻辑上更高级的方法。
代码1:
class Solution {
public:
bool validMountainArray(vector<int>& arr) {
if(arr.size()<3)
return false;
int high=0;
for(int i=1;i<arr.size();i++)
{
if(arr[i]==arr[i-1])
return false;
else if(arr[i]>arr[i-1])
high=i;
else
break;
}
if(high==0||high==arr.size()-1)
return false;
for(int i=high+1;i<arr.size();i++)
{
if(arr[i]>=arr[i-1])
return false;
}
return true;
}
};
思路2:
用双指针法。两个人爬山,一个从左到右,一个从右到左,如果是一个正确的峰型,应该都是一路上升,然后在同一点即山峰遇到。最后需要检查的是三件事:是不是在同一点遇到,左边是不是在数组第一位(一直降低的半峰),右边是不是在数组最后一位(一直增高的半峰),三点同时成立即可返回true。时间复杂度和思路1一样都是,但是个人感觉逻辑上这个更高级。
代码2:
bool validMountainArray(vector<int>& A) {
int n = A.size(), i = 0, j = n - 1;
while (i + 1 < n && A[i] < A[i + 1]) i++;
while (j > 0 && A[j - 1] > A[j]) j--;
return i > 0 && i == j && j < n - 1;
}