• 二分查找(Binary Search)的几种变种形式


    二分查找的几种变种形式

    二分查找是大家经常用而且也比较简单的一种算法,查找的时间复杂度为O(logn)。wiki上的定义为:

    是一種在有序陣列中尋找某一特定元素的搜尋演算法

    搜尋過程從陣列的中間元素開始,如果中間元素正好是要尋找的元素,則搜尋過程結束;如果某一特定元素大於或者小於中間元素,則在陣列大於或小於中間元素的那一半中尋找,而且跟開始一樣從中間元素開始比較。如果在某一步驟陣列為空,則代表找不到。這種搜尋演算法每一次比較都使搜尋範圍縮小一半。

    简单的二分查找算法相信大家都会写,但是有时候经常会遇到一些变种形式,会让人头痛。

    第一种:数组中没有重复元素,找到该元素返回该元素的下标,否则返回该元素的插入位置。

    非递归写法:

    public int binarySearch(int[] nums, int target) {
        int lo = 0;
        int hi = nums.length - 1;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (target < nums[mid]) hi = mid - 1;
            else if (nums[mid] < target) lo = mid + 1;
            else return mid;
        }
        return low;
    }
    

    递归写法:

     public int binarySearch(int[] nums, int target, int lo, int hi) {
        if (lo > hi) return lo;
        int mid = lo + (hi - lo) / 2;
        if (target < nums[mid]) return binarySearch(nums, target, lo, mid - 1);
        else if (nums[mid] < target) return binarySearch(nums, target, mid + 1, hi);
        else return mid;
    }
    

    第二种:数组中可能含有重复元素,找出目标元素的第一次出现的位置,否则返回该元素的插入位置。

    非递归写法:

    public int binarySearch(int[] nums, int target) {
        int lo = 0;
        int hi = nums.length - 1;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (nums[mid] < target) lo = mid + 1;
            else hi = mid - 1;
        }
        return lo;
    }
    

    递归写法

    public int binarySearch(int[] nums, int target, int lo, int hi) {
        if (lo > hi) return lo;
        int mid = lo + (hi - lo) / 2;
        if (nums[mid] < target) lo = mid + 1;
        else hi = mid - 1;
    }
    

    一点经验,二分查找的过程其实很简单,繁琐的点就在于结束的边界处,如果不熟练,一定不要怕麻烦,在纸上多画画检验下,看看最后结果是否正确。一个需要注意的点在于int mid = lo + (hi - lo) / 2;为什么不写成int mid = (lo + hi) / 2呢?因为lo + hi可能会出现整型溢出。

    其实上面的求边界还有一种写法:

    public int binarySearch(int[] A, int target) {
        int lo = 0
        int hi = A.length;
        while (lo < hi) {
            int mid = lo + (hi - lo) / 2;;
            if (A[mid] < target) {
                lo = mid + 1;
            } else {
                hi = mid;
            }
        }
        return lo;
    }
    

    大家可以比较下两种方法的不同点,其实不需要记这么多写法,容易把自己搞混,只需要记住一种正确写法就好。

  • 相关阅读:
    【转】Geary's C
    ArcGIS中影像与影像,影像与点云之间的配准
    [转] EPSG CODE的含义
    地图投影
    【从翻译mos文章】oracle linux 和外部存储系统 关系
    找呀志_使用SQLiteDatabase增删改提供的搜索方法和事务
    [049] 微信公众平台视频公开课1说话-基础知识
    我看到西电通院考试——学生应该做的事情?
    使用 Eclipse 的 SVN 主要插件创建项目/支/标签
    【SSH三个框架】Hibernate第十篇基础:inverse属性具体解释
  • 原文地址:https://www.cnblogs.com/ekoeko/p/9827262.html
Copyright © 2020-2023  润新知