做这道题目的问题在于,学会了套路,却忘记了分析问题的独特性。
当然,采取双指针我们可以在ON的时间复杂度解决。
OlogN这个条件其实暗示了很多信息,一般见到无非是二分查找或者二叉树搜索。我想了想,觉得二分查找一般好像是找某个范围内的整数 ,想了想好像对这个题目没什么影响。然后就想怎么把这些数据放到搜索树然后能解决问题了。
重要的一点在于,没有关注两侧是负无穷这个条件。如果没有这个条件,问题都是局部的,nums[1]是不是峰值和nums[5]是不是峰值之间好像没有什么关系,只需要关注前面和后面两个值才能判断。
具体分析这个题目,其实归纳出的规律是:“只要数组中存在一个元素比相邻元素大,那么沿着它一定可以找到一个峰值”。
首先,整个区间必然会出现峰值,无论是单调增减,单峰还是驼峰。
其次,设想一下,nums[n]到nums[length-1]这个区间不出现峰值有哪些可能情况(二分法的思维):
唯一的可能就是这段区间[nums[n-1],nums[length-1]单调递减。
所以来捋一捋二分法的几个关键条件:
- 区间划分:采取传统的左闭右开区间,左右分别为l,r,初始设置为0,length
- 终止条件:当区间只有一个值时,即while(r>l+1)时进行二分
- mid=l+r /2,区间分别是[l,mid),[mid,r)。当nums[mid]>nums[mid-1]时右区间有峰值,反之左区间有峰值
所以代码就出来了:(迭代二分法,当然还有递归的二分法)
public class Solution { public int findPeakElement(int[] nums) { int l = 0, r = nums.length; while (l +1 < r) { int mid = (l + r) / 2; if (nums[mid] > nums[mid - 1]) l = mid; else r = mid; } return l; } }
这道题给我的启发是:二分法的中心在于能通过比较区分范围是在左区间还是右区间,什么整数什么的都是外壳