二分查找以及其变种总结
图片、原文来自:https://www.cnblogs.com/luoxn28/p/5767571.html
以下图片中源码手写板来自:https://github.com/qq249356520/AlgorithmNotes Search文件夹
上图分别解释了二分查找成功和失败的两种情况。当left > right时二分查找失败(所给数组中没有待查找元素)。
基本的二分查找如下:要求数组有序
常规二分查找
如果把需要查找的条件稍微变换一下,比如数组中多个重复元素,要求找到匹配的数据最小(或最大)的下标;更进一步,需要找出数组中第一个大于key的元素(也就是数组中最小的大于k的元素)下标,等等。
其变种与二分查找原理一样,都是变换判断条件(边界条件)。
第一种:查找第一个与key值相等的元素的下标(常规二分查找的变种)
边界条件改变:当arr[mid]>key加等号,改为>=。因为要寻找最左元素,所以需要用left判断。
循环退出条件:left刚好指向key,right指向key的前一个元素。
第二种:查找第一个大于等于key值的元素的下标(第一种的变种)
第三种:查找第一个大于key值元素的下标(第一种与第二种的变种)
第四种:查找最后一个与key值相等的元素的下标(常规二分的变种)
边界条件改变:当arr[mid] < key时加等号,因为要寻找最后一个。
循环退出条件:left指向刚好大于要查找元素的元素,right指向待查找元素
第五种:查找最后一个小于等于key值元素的下标(第四种的变种)
第六种:查找最后一个小于key值元素的下标(第四种与第五种的变种)
测试用例:
总结:
我们可按照以下步骤总结二分查找变种:
1、首先判断返回left还是返回right:
因为结束循环的条件是left <= right,所以最后的结果必定是left = right + 1,left和right卡在边界的两边
如果比较值为k,当我们查找小于等于k的元素,则边界值就是所有等于k的最左边的那个,应该返回left
2、判断比较符号:
也就是?的符号,同上,如果是查找小于等于k的元素,那么我们应该使用 <= k 控制left 如果大于等于则 >= 控制right