题目解析
本题意在一个数组中找出一个峰值,这个题目用暴力求解也可以去做,方法就是将数组遍历一遍,然后找出其中一个峰值即可,但是其时间复杂度就会是O(n),而不是题目要求的O(logN)。
那我们就从另一个角度去分析该题,题目是让我们找到峰值,峰值的概念就是其左右元素都比它小。 然后我们在来分析峰值左右元素的规律,峰值的左侧元素一定是局部递增序列,峰值的右侧一定是局部递减序列,我们知道了这个规律后就可以使用变形的二分查找方法来找出峰值。
举例说明:
数组a[] = {1, 2, 3, 2, 5 ,6, 7, 2};
在该例子中,有两个峰值元素,3和7。分析该数字左右两侧的局部序列,发现左侧递增右侧局部递减。
如果a[mid] > a[mid + 1] (就是该元素比其右侧元素大,那就证明峰值是其本身或者在其左侧序列中)
如果a[mid] < a[mid + 1] (那就证明峰值肯定在其右侧序列,肯定不是a[mid])。
这两句话可以结合上面的规律好好理解
然后代码的分割点也找到之后,这道题就已经可以求解了。利用二分查找我们就可以将时间复杂度降到O(logn)。
完整代码如下:
class Solution {
public:
int findPeakElement(vector<int>& nums)
{
return find(nums, 0, nums.size() -1);
}
int find(vector<int> &nums, int low, int high)
{
if(low == high)
return low;
int mid = (low + high) / 2;
if(nums[mid] > nums[mid + 1])
{
return find(nums, low, mid);
}
return find(nums, mid + 1, high);
}
};