二分查找及变形总结

参考:
https://blog.csdn.net/zxzxzx0119/article/details/82670761

共7中情况:(假设要找的元素为key)
(1)普通二分;
(2)第一个等于key的;(3)第一个大于等于key的;(4)第一个大于key的
(5)最后一个等于key的;(6)最后一个大于等于key的;(5)最后一个大于key的;

代码通用部分:
(1)while循环条件都是L<=R;
(2)判断条件里都是arr[mid]和key进行比较,且arr[mid]在前

不同部分口诀:一大二小,一左二右,等于要判断
解释:
(1)一大二小(其实要求是什么判断条件就写成什么,比如要求第一个大于等于,就写>=, 最后一个小于等于就写<=)
找第一个。。。的(即2,3,4三种情况),判断条件都是arr[mid]>key或者arr[mid]>=key;找最后一个。。。的(即5,6,7三种情况),判断条件都是arr[mid]<key或者arr[mid]<=key
当要求中含有等于要求时(即等于key, 大于等于key,小于等于key),判断条件加上等于号(>= 或者<=),否则(大于key,小于key)判断条件不加等号(>或者<)

(2)一左二右
找第一个。。。的(即2,3,4三种情况),返回的都是R;找最后一个。。。的(即5,6,7三种情况),返回的都是L。

(3)等于要判断
如果是找第一个等于key或者最后一个等于key的还需要在while结束后加上判断找到的是否合法的条件。
第一个等于key:
由于返回的是L,需要对L进行判断

L<arr.size() && arr[L]==key

最后一个等于key的:
由于返回的是R,需要对R进行判断

R>=0 && arr[R]==key

————————————————————————————————————
以下是代码:
(1)普通二分


		int L = 0,R = arr.length - 1; //在[L,R]范围内寻找key
        int mid;
        while( L <= R){
            mid = L + (R - L) / 2;
            if(arr[mid] == key)
                return mid;
            if(arr[mid] > key)
                R = mid - 1;// key 在 [L,mid-1]内
            else
                L = mid + 1;
        }
        return -1;
    

(2)第一个等于key的

        int L = 0, R = arr.length - 1;
        int mid;
        while( L <= R){
            mid = L + (R - L)/2;
            if(arr[mid] >= key)  //一大,要求有等于加等号
                R = mid - 1;
            else
                L = mid + 1;
        }
        if(L < arr.length && arr[L] == key) //等于要判断
            return L;   //一左
        return -1;

(3)第一个大于等于key的

        int L = 0, R = arr.length - 1;
        int mid;
        while( L <= R){
            mid = L + (R - L) / 2;
            if(arr[mid] >= key)  //一大,要求有等于加等号
                R = mid - 1;
            else
                L = mid + 1;
        }
        return L;  //不是等于不判断,一左

(4)第一个大于key的

        int L = 0,R = arr.length - 1;
        int mid;
        while(L <= R){
            mid = L + (R - L) / 2;
            if(arr[mid] > key)  //一大,不要求有等于不加等号
                R = mid - 1;
            else
                L = mid + 1;
        }
        return L;  //不是等于不判断,一左

(5)最后一个等于key的

		int L = 0, R = arr.length - 1;
        int mid;
        while( L <= R){
            mid = L + (R - L)/2;
            if(arr[mid] <= key)  //二小,要求等于要加等号
                L = mid + 1;
            else
                R = mid - 1;
        }
        if(R >= 0 && arr[R] == key)  //是等于要判断
            return R;   //二右
        return -1;

(6)最后一个小于等于key的

		int L = 0, R = arr.length - 1;
        int mid;
        while( L <= R){
            mid = L + (R - L) / 2;
            if(arr[mid] <= key)   //二小,要求等于要加等号
                L = mid + 1;
            else
                R = mid - 1;
        }
        return R;   //不是等于不用判断,二右

(7)最后一个小于key的

		int L = 0, R = arr.length - 1;
        int mid;
        while(L <= R){
            mid = L + (R - L) / 2;
            if(arr[mid] < key)   //二小,不要求等于不要加等号
                L = mid + 1;
            else
                R = mid - 1;
        }
        return R;   //不是等于不用判断,二右

猜你喜欢

转载自blog.csdn.net/aikudexue/article/details/88831913