二分法查找是一种应用非常广泛的查找算法,这里有二点需要说明:
1、查找的数组必须是有序数组,无论升序还是降序排列都可以。
2、时间复杂度为O(log)。
举一个二分法例子:
我随便想一个1~100的数字,你的目标是以最少的次数猜到这个数字,假设要猜的数字是75
你:50
我:猜的数字小了
你:80(这时你肯定会在50~100内猜数字,因为他说过50小了)
我:猜的数字大了
你:70
............
就这样下去一定能猜对.。
首先是leetcode最简单的一道题:
代码实现Java版:
public int search(int[] nums, int target) {
int left=0;
int right=nums.length-1;
while(left<=right){
int mid=(left+right)/2;
if(target==nums[mid]){
return mid;
}else if(target>nums[mid]){
left=mid+1;
}else{
right=mid-1;
}
}
return -1;
}
至于循环判断条件使用left<=right还是用left<right:
1、如果查找的区间是左闭,右闭即[0,nums.length-1],就可以用left<=right,因为left=right是有意义的。
2、反之,若区间是左闭,右开即[0,nums.length),此时left=right是无意义的,应该用left<right
更加详细的介绍请看这位大佬的文章:https://mp.weixin.qq.com/s/4X-8VRgnYRGd5LYGZ33m4w
类似的一道题:
public int searchInsert(int[] nums, int target) {
int left=0;
int right=nums.length-1;
while(left<=right){
int mid=left+(right-left)/2;//防止溢出,更加高级的一种写法
if(nums[mid]==target){
return mid;
}else if(nums[mid]<target){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
更进一步:
public int findMin(int[] nums) {
int left=0;
int right=nums.length-1;
while(left<right){
int mid=(left+right)/2;//mid之后必然把数组分为两部分,一部分乱序,一部分按升序排列,而最小值一定在乱序的那部分数组里面
if(nums[left]<nums[right]){
return nums[left];
}else if(nums[mid]<nums[right]){//有序的部分
right=mid;
}else{//l乱序的部分
left=mid+1;
}
}
return nums[left];
}