二分查找
-
使用条件:(1)有序 (2)无重复数据
-
具体理论:具体理论就是,会设置两个指针,分别为left和right,left指向数组的首位,right指向最后一个位置 ,或者最后一个位置的后一位(这里就区分出是左闭右闭区间还是左闭右开区间),然后查找某一个数值时,由left和right得出一个中间值mid,判断该mid是否为所求的值,如果是则返回索引或者做其他操作,如果大于目标值,则让right变为mid-1(左闭右闭),再次求mid;如果小于目标值,则将left变为mid+1,直到查找完整个数据或者找到目标数据。
-
两中区间定义:
(1)左闭右闭区间,是指left为首地址的值,right为末尾地址的值,即[left,right],二分查找的实质就是根据条件更新这个边界,比如中间值大了,那就调整right,那么right怎么调整呢,如果right = mid,则更新区间为[left,mid],显然mid还要再做一个边界判断,不合理,所以right应该为mid-1,左边界同理,不做过多解释,代码如下:
class Solution { public int search(int[] nums, int target) { //左闭右闭 int left = 0; int right = nums.length-1; if(nums.length == 0){ return -1; }else{ while(left<=right){ int middle = (left+right)/2; if(target > nums[middle]){ left = middle + 1; }else if(target < nums[middle]){ right = middle - 1; }else{ return middle; } } } return -1; } }(2)左闭右开区间同理,就是一个换区间的问题,开始区间为[left,right),在搜索一次后,显然不包含right,所以循环终止条件right不能等于left,假设目标值大于mid,则要调整边界值,如果调整边界值为mid-1,则区间范围为[left,mid-1),则不包含mid-1,就会出问题,所以调整为[left,mid)。代码如下:
class Solution { public int search(int[] nums, int target) { //左闭右闭 int left = 0; int right = nums.length; if(nums.length == 0){ return -1; }else{ while(left<right){ int middle = (left+right)/2; if(target > nums[middle]){ left = middle+1; }else if(target < nums[middle]){ right = middle; }else{ return middle; } } } return -1; } }