leetcode算法之二分查找

53 阅读2分钟

二分查找

1. 二分查找的的基本思路

1. 首先选择数组中间的数字和需要查找的目标值比较
2. 如果相等最好,就可以直接返回答案了
3. 如果不相等
  - 如果中间的数字大于目标值,则中间数字向右的所有数字都大于目标值,全部排除
  - 如果中间的数字小于目标值,则中间数字向左的所有数字都小于目标值,全部排除

如何确认边界

边界问题就是左闭右闭还是左闭右开的的选择,那么我们首先要弄清左闭右闭和左闭右开都是怎么回事。如下图:
-   左闭右闭代表的就是[left,right]的区间,也就是left = 0,right = numsSize - 1
-   左闭右开代表的就是[left,right)的区间,也就是left = 0,right = numsSize

image.png

代码实现

/**
 * 左闭右开 [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选择的几道题中左闭右闭和左闭右开都可以解决。后面如果出现了差异在补充。

刷题链接