二分查找
1. 二分查找的的基本思路
1. 首先选择数组中间的数字和需要查找的目标值比较
2. 如果相等最好,就可以直接返回答案了
3. 如果不相等
- 如果中间的数字大于目标值,则中间数字向右的所有数字都大于目标值,全部排除
- 如果中间的数字小于目标值,则中间数字向左的所有数字都小于目标值,全部排除
如何确认边界
边界问题就是左闭右闭还是左闭右开的的选择,那么我们首先要弄清左闭右闭和左闭右开都是怎么回事。如下图:
- 左闭右闭代表的就是[left,right]的区间,也就是left = 0,right = numsSize - 1
- 左闭右开代表的就是[left,right)的区间,也就是left = 0,right = numsSize
代码实现
/**
* 左闭右开 [left, right)
* @param nums
* @param target
* @return
*/
public int search(int nums[], int target) {
int left = 0;
int right = nums.length;
while (left < right) {
//等同于 (left + right) / 2,防止溢出
int middle = left + ((right - left) / 2);
if (nums[middle] > target) {
right = middle;
} else if (nums[middle] < target) {
left = middle + 1;
} else {
return middle;
}
}
// 没找到就返回-1
return -1;
}
/**
* 左闭右闭 [left, right]
* @param nums
* @param target
* @return
*/
public int search(int nums[], int target) {
int left = 0;
int right = nums.length - 1;// 差异一
while (left <= right) {// 差异二
//等同于 (left + right) / 2,防止溢出
int middle = left + ((right - left) / 2);
if (nums[middle] > target) {
right = middle - 1;// 差异三
} else if (nums[middle] < target) {
left = middle + 1;
} else {
return middle;
}
}
//没有找到目标值
return -1;
}
那么左闭右闭中left < right行不行呢?反之在左闭右开中left <= right呢
不行哒!
举个例子:nums = [-1,2,4,6,8,12,44,62,64,71,90],target = 62 -> idx = 7
左闭右闭中`left < right`: left = 0, right = 10
第一轮: middle = 5 nums[5] = 12 < 44,所以left = 6 | right = 10
第二轮:middle = 8 nums[8] = 64 > 62,所以right = 7 | left = 6
第三轮:middle = 6 nums[6] = 44 < 62,所以left = 7 | right = 7
这样target没有找到,而左闭右开中使用`left <= right`亦是同理
那么左闭右闭和左闭右开在选择上有什么区别呢
暂时没有发现有什么区别,leetcode选择的几道题中左闭右闭和左闭右开都可以解决。后面如果出现了差异在补充。
刷题链接