美文网首页
数据结构与算法之美笔记——二分查找(下)

数据结构与算法之美笔记——二分查找(下)

作者: Cloneable | 来源:发表于2019-07-07 16:42 被阅读0次

摘要:

基础的二分查找算法无论是概念还是实现都比较简单(关于 二分查找基础实现文章 可点击此处查看),但二分查找存在相对复杂的变体问题,如数据组中存在重复数据时需要查找第一个或最后一个等于目标数据的情况等,而类似的变体问题也是二分查找的应用场景,也就是查找近似值。

二分查找的变体

基础的二分查找实现比较简单,简单的二分查找能够解决的问题应用其他查找算法也同样可以实现,执行效率也相差无几,但二分查找这种算法的存在是有自己的应用场景的。

之前讲述二分查找的例子中数据比较简单,需要解决的问题也不复杂,首先数据中没有重复数据,其次解决的问题只是在数据组中找到目标数据对应元素。如果改变条件,数据组中有重复数据,需要查找数据组中第一位或最后一位等于目标数据的情况,这样的问题该如何用二分查找解决?类似的,如果是查找数据组中第一位大于等于或最后一位小于等于目标数据的情况,应用二分查找又该如何解决?

解决问题的思路

上面几种二分查找变体问题都是类似的,我们可以先思考「重复数据情况下查找第一位等于目标数据」的问题。

基本思路还是二分查找的实现思路,不过因为有重复数据,当查找到目标数据时需要再做一番思考。虽然此时查找到了目标数据,但不一定是第一位等于目标数据的数组元素。此时有两种情况,一种是当前元素就是第一位等于目标数据的数组元素,那当前元素应当满足其是数组的首位元素(其前一位没有数据)或其前一位元素不等于目标数据;另一种是当前元素不满足上一种情况的条件,也就是说不是第一位等于目标数据的数组元素,那需要查找到的元素肯定在当前元素之前,需要对这部分数据再次进行二分查找。

代码实现

查找第一位等于目标数据的元素

public static int searchFirstEqual(int[] a, int target) {
    if(a.length < 1) { return -1;}

    int high = a.length - 1, low = 0;
    while(low <= high) {
        int mid = low + ((high - low) >> 1);
        if (a[mid] > target) {
            high = mid - 1;
        } else if(a[mid] < target) {
            low = mid + 1;
        } else {
            if(mid == 0 || a[mid - 1] != target) {
                return mid;
            }
            high = mid - 1;
        }
    }

    return -1;
}

查找最后一位等于目标数据的元素

这个问题的解决思路与「查找第一位等于目标数据的元素」问题类似,只是第一位换作了最后一位,需要将查找到的元素判断条件修改一下,当查找到元素等于目标数据时,当前元素要不就是数组最后一个元素,要不其下一个元素不等于目标数据,否则在需要查找的元素肯定在当前元素之后,需要对这部分数据继续使用二分查找。

public static int searchLatestEqual(int[] a, int target) {
    if(a.length < 1) { return -1;}

    int high = a.length - 1, low = 0;
    while(low <= high) {
        int mid = low + ((high - low) >> 1);
        if (a[mid] > target) {
            high = mid - 1;
        } else if(a[mid] < target) {
            low = mid + 1;
        } else {
            if(mid == a.length - 1 || a[mid + 1] != target) {
                return mid;
            }
            low = mid + 1;
        }
    }

    return -1;
}

查找第一位大于等于目标数据的元素

解决了前两个问题再来解决这个问题也就不难了,与「查找第一位等于目标数据的元素」问题相比,无非就是将等于换成了大于等于,修改相应的判断条件即可。

public static int searchFirstGte(int[] a, int target) {
    if(a.length < 1) { return -1;}

    int high = a.length - 1, low = 0;
    while(low <= high) {
        int mid = low + ((high - low) >> 1);
        if (a[mid] >= target) {
            if(mid == 0 || a[mid - 1] < target) {
                return mid;
            }
            high = mid - 1;
        } else if(a[mid] < target) {
            low = mid + 1;
        }
    }

    return -1;
}

查找最后一位小于等于目标数据的元素

比较一下问题,就知道这个问题与「查找最后一位等于目标数据的元素」问题相似度高达 99.99%,只要将相应的判断条件修改一下即可。

public static int searchLatestLte(int[] a, int target) {
    if(a.length < 1) { return -1;}

    int high = a.length - 1, low = 0;
    while(low <= high) {
        int mid = low + ((high - low) >> 1);
        if (a[mid] > target) {
            high = mid - 1;
        } else if(a[mid] <= target) {
            if(mid == a.length - 1 || a[mid + 1] > target) {
                return mid;
            }
            low = mid + 1;
        }
    }

    return -1;
}

总结

二分查找虽然简单,但解决变体问题时还是需要思考一番,在变体问题的代码实现时,需要注意 确定返回数据的条件low 和 high 的数据更新

尽管还有其他出色的查找算法,但二分查找在近似数据查找的问题上非常适合,在实际中像「IP 归属地查找」等问题都符合近似查找,解决这些问题也是二分查找的用武之地。


文章中如有问题欢迎留言指正
本章节代码已经上传GitHub,可点击跳转查看代码详情。
数据结构与算法之美笔记系列将会做为我对王争老师此专栏的学习笔记,如想了解更多王争老师专栏的详情请到极客时间自行搜索。

相关文章

  • 二分查找

    学习极客时间的数据结构与算法之美的专栏,记录笔记。 1 二分查找应用场景的局限性 (1)二分查找依赖的是顺序表结构...

  • 排序算法

    算法与数据结构基础 查找算法: 二分查找法: 简介:二分查找法又被称为折半查找法,用于预排序的查找问题 过程: 如...

  • 2019-10-27文章阅读

    二分查找(上):如何用最省内存的方式实现快速查找功能? 来源:王争的数据结构与算法之美时间复杂度为O(logn) ...

  • 20181205_ARTS_W9

    Algorithm 数据结构与算法之美之变形二分查找大前提:都是有序数组,可能存在重复元素 查找第一个等于某个数值...

  • 数据结构与算法

    数据结构与算法之美 数据结构与算法之美1--如何学数据结构与算法之美2--复杂度分析(上)数据结构与算法之美3--...

  • 数据结构与算法之美笔记——二分查找(下)

    摘要: 基础的二分查找算法无论是概念还是实现都比较简单(关于 二分查找基础实现文章 可点击此处查看),但二分查找存...

  • 常考的数据结构与算法之算法

    本文记录一下我学习数据结构与算法中算法的知识点,使用的语言是C/C++语言 查找 二分查找又叫折半查找,要求线性表...

  • 数据结构与算法--散列表

    数据结构与算法--散列表 之前学习了基于链表的顺序查找、基于有序数组的二分查找、二叉查找树、红黑树,这些算法在查找...

  • 数据结构与算法 树 引言 顺序查找 ​ 哨兵的方式 ​ 时间复杂度为O(N) 二分查找查找树的形式我...

  • 02数据结构与算法复杂度分析上

    数据结构与算法之美专栏笔记 1. 为什么要学习数据结构和算法 数据结构和算法本身解决的是“快”和“省”的问题,让代...

网友评论

      本文标题:数据结构与算法之美笔记——二分查找(下)

      本文链接:https://www.haomeiwen.com/subject/fwtihctx.html