二分查找法总结:
第一:使用条件为有序或者部分有序的数组
第二:一定要弄清楚整个算法是在左闭右闭还是左闭右开的区间内完成
第三:为了有效的防止中间数据的溢出,所以mid条件一般写为:Mid = left +((right – left)/ 2)
代码:左闭右闭 [left,right]
注意点1:为什么while循环的条件是left<=right,而不是left<right。这里就需要你对区间有所了解。举个例子 当我们的数组为[1,3,5,6],那么我们right此时的长度就是4-1=3,那么闭区间[left:0,right:3],当数组在循环的时候right就是数组的最后一个元素,那么left=3后,在这个【3,3】这个区间是合法的。
总的来说这里的循环条件只要满足区间是合法就ok了
注意点 2:为了防止在计算mid值时数组的越界情况,一般建议使用mid = left + ((right - left)/2)
是等同于下面代码所提供的mid = (left + right) / 2的
注意点3:对于right 到底是mid + 1还是mid的情况 也是结合着你到底是闭区间还是开区间来结合的,代码块里面有说明此处就不再重述了。
/**
* 输入: nums = [1,3,5,6], target = 2
* 输出: 1
*/
// 二分查找法
public static int searchInsert4(int[] nums, int target) {
int left = 0;
int right = nums.length - 1; // 注意边界是[left,right] // [0,3]
while (left <= right){ // 所以此处循环是left<=right
int mid = (left+right)/2; // 取left和right的中间值mid 注意:此处可能会出现int越界的情况
if (nums[mid]>target){ // 当中间值小于了目标值,那么说明目标值在[left,mid]这个区间,所以需要更新right值
right = mid - 1; // 此处为什么是mid-1。由于我们是左闭右闭的区间,在if条件中已经明确知道了mid处的值是大于了目标值所以可以明确目标值所在数组位置一定是在区间为[left,mid-1]
} else if (nums[mid] < target){ // 当中间值大于了目标值,那么说明目标值在[mid,right]这个区间,所以需要更新left值
left = mid + 1; // 此处为什么是mid+1。由于我们是左闭右闭的区间,在if条件中已经明确知道了mid处的值是小于了目标值所以可以明确目标值所在数组位置一定是在区间为[mid+1,right]
} else { // 最后就是mid = 目标值的情况,直接放回mid的即是目标值在数组中的位置
return mid;
}
}
return -1; // 目标值不在数组的情况可以选择放回-1
}
代码:左闭右开 [left,right])
注意点同上述,理解好区间的合法性就能理解此处代码
/**
* nums = [1,3,5,6], target = 2
*/
public static int searchInsert5(int[] nums, int target) {
if (nums[0] > target){
return 0;
}
int left = 0;
int right = nums.length; // 注意边界是[left,right] // [0,4)
while (left < right){ // 所以此处循环是left<right
int mid = (left+right)/2; // 取left和right的中间值mid 注意:此处可能会出现int越界的情况
if (nums[mid]>target){ // 当中间值小于了目标值,那么说明目标值在[left,mid]这个区间,所以需要更新right值
right = mid; // 此处为什么是mid-1。由于我们是左闭右闭的区间,在if条件中已经明确知道了mid处的值是大于了目标值所以可以明确目标值所在数组位置一定是在区间为[left,mid-1]
} else if (nums[mid] < target){ // 当中间值大于了目标值,那么说明目标值在[mid,right]这个区间,所以需要更新left值
left = mid + 1; // 此处为什么是mid+1。由于我们是左闭右闭的区间,在if条件中已经明确知道了mid处的值是小于了目标值所以可以明确目标值所在数组位置一定是在区间为[mid+1,right]
} else { // 最后就是mid = 目标值的情况,直接放回mid的即是目标值在数组中的位置
return mid;
}
}
return nums.length; // 目标值不在数组的情况可以选择放回-1
}