题目:
Let’s call an array
A
a mountain if the following properties hold:
A.length >= 3
There exists some0 < 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 anyi
such thatA[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.
解释:
二分查找的应用,寻找山峰的峰值。
二分查找python代码:
def BinarySearch(nums,target):
left,right=0,len(nums)-1
#注意这里一定要是"<="
while(left<=right):
middle=left+(right-left)//2
if nums[middle]==target:
return middle
#注意这里left和right的更新
elif nums[middle]<target:
left=middle+1
else:
right=middle-1
return -1
nums=[1,2,3,4,5,6,7,8,9]
target=1
print (BinarySearch(nums,target))
这道题目,只需要比较mid
和mid+1
所指向的值,因为考虑到mid+1
,所以循环的条件是left<right
,返回值是left
(若,条件是left<=right的话,当right和left都指向最后一个元素时,此时mid
也指向最后一个元素,mid+1
不在范围内),同时要注意left
和right
的更新,
若 nums[mid]<nums[mid+1]
,此时mid
一定在山峰的左边,所以更新 left=mid+1
,
若 nums[mid]>=nums[mid+1]
,此时mid
可能在山峰的右边,也有可能是山峰本身,所以不能是right=mid-1
,而应该是 right=mid
,这样做是为了防止mid
是山峰本身的时候漏掉了山峰,进而又跳到了山峰左边的情况导致求不出值的情况。
python代码:
class Solution(object):
def peakIndexInMountainArray(self, A):
"""
:type A: List[int]
:rtype: int
"""
n=len(A)
left,right=0,n-1
while left<right:
mid=left+(right-left)//2
if A[mid]<A[mid+1]:
left=mid+1
else:
right=mid
return left
c++代码:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& A) {
int left=0,right=A.size()-1;
while(left<right)
{
int mid=left+(right-left)/2;
if(A[mid]<A[mid+1])
left=mid+1;
else
right=mid;
}
return left;
}
};
拓展:
找到一个排好序的数组中绝对值最小的元素。
python代码:
def findMinAbs(nums):
left,right=0,len(nums)-1
while(left<right):
mid=left+(right-left)//2
if nums[mid]==0:
return nums[mid]
#注意这里对left和right的更新方式,因为不确定mid是不是绝对值最小的
#所以不能用mid+1和mid-1来更新left和right
elif nums[mid]>0:
right=mid
else:
left=mid
if (right-left==1):
return nums[left] if abs(nums[left])<abs(nums[right]) else nums[right]
nums1=[-9,-8,-7,-6,-2,0,1,2,3,4,5]
nums2=[2,3,4,5,6,7]
nums3=[-9,-8,-7,-6,-2]
nums4=[-9,-8,-7,-6,-2,3,4,5]
nums5=[-9,-8,-7,-6,3,4,5]
print(findMinAbs(nums1))
print(findMinAbs(nums2))
print(findMinAbs(nums3))
print(findMinAbs(nums4))
print(findMinAbs(nums5))
总结:
二分查找本身很容易,但是对于循环判断条件和更新指针的时候有很多细节是值得注意的,二分查找有很多拓展应用。