寻找中间值大于左右值,且时间复杂度为O(logN),想到使用折半查找。
折半查找
/*折半查找*/
int Binary_Search(int a*,int n,int key)
{
int low,high,mid;
low=1; /*定义最底下标为记录首位*/
high=n; /*定义最高下标为记录末位*/
while(low<=high)
{
mid=(low+high)/2; /*折半*/
if(key<a[mid])
high=mid-1;
if(key>a[mid])
low=mid+1;
else
return mid;
}
return 0;
}
解决方案
先找到mid对应的元素nums[mid],然后判断是否比nums[mid-1]大,比nums[mid+1]小,来确定其是否是峰值。
如果是峰值,那么直接返回mid。
不是峰值,就需要重新确定low和high。
如果nums[mid]>nums[mid+1],那么峰值有可能出现在mid的左侧;反之可能出现在mid的右侧。通过这种策略来重新确定low和high。
主体代码:
while (low < high){
mid = (low + high) / 2;
if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]){
return mid;
}else {
if (nums[mid] < nums[mid + 1]){
low = mid + 1;
}else {
high = mid - 1;
}
}
}
情况一
如果数组的长度小于3,那么就单独处理一下:
if (length == 1){
return 0;
}
if (length == 2){
return nums[0] > nums[1] ? 0: 1;
}
情况二
防止mid-1和mid+1越界,重新调整mid的位置:
if (mid - 1 < 0){
temp = 1;
}
if (mid + 1 == length){
temp = -1;
}
mid += temp;
情况三
遇到递增或者递减的情况,即low和high相等
if (low == high){
return high;
}
整体代码:
class Solution {
public int findPeakElement(int[] nums) {
int length = nums.length;
int low = 0,high = length - 1,mid,temp = 0;
if (length == 1){
return 0;
}
if (length == 2){
return nums[0] > nums[1] ? 0: 1;
}
while (low < high){
mid = (low + high) / 2;
if (mid - 1 < 0){
temp = 1;
}
if (mid + 1 == length){
temp = -1;
}
mid += temp;
if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]){
return mid;
}else {
if (nums[mid] < nums[mid + 1]){
low = mid + 1;
}else {
high = mid - 1;
}
}
}
if (low == high){
return high;
}
return -1;
}
}