Let's call an array `A` a *mountain* if the following properties hold:
A.length >= 3
- There exists some
0 < i < A.length - 1
such thatA[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]
Given an array that is definitely a mountain, return any i
such that A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]
.
Example 1:
Input: [0,1,0]
Output: 1
Example 2:
Input: [0,2,1,0]
Output: 1
Note:
3 <= A.length <= 10000
0 <= A[i] <= 10^6
- A is a mountain, as defined above.
這道題定義了一種山形的數組,說是有一個最高點,然后向兩邊各自降低,讓我們找出山峰的位置。其實這道題跟之前那道 [Find Peak Element](http://www.cnblogs.com/grandyang/p/4217175.html) 非常的類似,只不過那道題有很多局部峰值,而這里道題只有一個全局峰值。題目中限定了山峰一定存在,即一定有一個最高點,反應在數組中就是最大值,那么問題就轉換為了求數組中最大值的位置,最簡單直接的方法就是遍歷數組找出最大值的位置即可,這里使用了 STL 的內置函數 max_element() 來一行解題,參見代碼如下:
解法一:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& A) {
return max_element(A.begin(), A.end()) - A.begin();
}
};
由於題目中限定了山峰一定存在,所以我們也可以直接直接來找第一個下降的位置,即 A[i] > A[i+1] 的地方,那么i位置一定就是山峰了,注意i的遍歷范圍要去掉首尾兩個數字,參見代碼如下:
解法二:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& A) {
for (int i = 1; i < (int)A.size() - 1; ++i) {
if (A[i] > A[i + 1]) return i;
}
return 0;
}
};
上面兩種解法都是線性的時間復雜度,能不能更快一點呢?那么就只有使用二分搜索法來加快搜索速度了,其實這是博主的總結帖 [LeetCode Binary Search Summary 二分搜索法小結](http://www.cnblogs.com/grandyang/p/6854825.html) 中的第五類情況,跟前的稍有不同的是 right 的初始化,之前的情況博主基本上都是用數組長度初始化 right 的,但是這里要用數組長度減1來初始化 right,因為要跟緊鄰的右邊的數字比較,這樣初始化 right 的意義在於 mid+1 就不會越界了,參見代碼如下:
解法三:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& A) {
int n = A.size(), left = 0, right = n - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (A[mid] < A[mid + 1]) left = mid + 1;
else right = mid;
}
return right;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/852
類似題目:
參考資料:
https://leetcode.com/problems/peak-index-in-a-mountain-array/