二分查找的思想是在已经排序(升序)的数组中,如果要查找的数比中位数小,那么其位置只可能在左半部分,相反只能在右半部分。这样每次把查找区间缩小一半,比顺序查找效率快得多。
非递归写法:
public static int binarySearchInAscLooply(int[] nums,int start,int end,int t){
if(nums==null||nums.length<=end) throw new IllegalArgumentException("输入不合法");
int mid;
int found=-1;
while(found==-1&&start<=end){
mid=(start+end)/2;
if(nums[mid]==t){
found=mid;
}else if(nums[mid]>t){
end=mid-1;
}else{
start=mid+1;
}
}
return found;
}
传入start和end索引而不是在函数内部固定死为0和nums.length-1是为了提高函数复用性。
递归写法:
public static int binarySearchInAscRecursively(int[] nums,int start,int end,int t){
if(nums==null||nums.length<=end) throw new IllegalArgumentException("输入不合法");
int found=-1;
if(start>end) return found;
int mid=(start+end)/2;
if(nums[mid]==t){
found=mid;
}else if(nums[mid]>t){
found=binarySearchInAscRecursively(nums,start,mid-1,t);
}else{
found=binarySearchInAscRecursively(nums,mid+1,end,t);
}
return found;
}
有时候我们可能需要查找升序数组中第一个比目标值大的位置(例如二分插入排序),比较中位数与目标值,存在两种情况:
1、中位数比目标值大,但是中位数不一定是第一个比它大,如果前一个数比它小,则当前中位数就是一个比目标值大的位置,否则要继续向前查找。
2、中位数比目标值小或者相等,需要继续往后找。
public static int binarySearchFirstBiggerInAsc(int[] nums,int start,int end,int t){
if(nums==null||nums.length<=end) throw new IllegalArgumentException("输入不合法");
int mid;
while(start<=end){
mid=(start+end)/2;
if(nums[mid]>t){
end=mid-1;
}else{
start=mid+1;
}
}
return end+1;
}
这里如果数组中没有比查找值大的,返回end+1,表明第一个比目标值大的位置至少是end+1。