侧边栏壁纸
博主头像
意义Meaning

每天过的都要有意义

  • 累计撰写 12 篇文章
  • 累计创建 12 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

《数据结构与算法》——二分查找法

意义Meaning
2024-11-25 / 0 评论 / 0 点赞 / 7 阅读 / 0 字
温馨提示:
本文最后更新于2024-11-25,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

二分查找算法也称折半查找,是一种非常高效的工作于有序数组的查找算法。后续的课程中还会学习更多的查找算法,但在此之前,不妨用它作为入门。

1) 基础版

需求:在有序数组 A 内,查找值 target

  • 如果找到返回索引

  • 如果找不到返回 -1

算法描述

前提

给定一个内含 $n$ 个元素的有序数组 $A$,满足 $A{0}\leq A{1}\leq A{2}\leq \cdots \leq A{n-1}$,一个待查值 target

1

设置 $i=0$,$j=n-1$

2

如果 $i \gt j$,结束查找,没找到

3

设置 $m = floor(\frac {i+j}{2})$ ,$m$ 为中间索引,$floor$ 是向下取整($\leq \frac {i+j}{2}$ 的最小整数)

4

如果 $target < A_{m}$ 设置 $j = m - 1$,跳到第2步

5

如果 $A_{m} < target$ 设置 $i = m + 1$,跳到第2步

6

如果 $A_{m} = target$,结束查找,找到了

P.S.

  • 对于一个算法来讲,都有较为严谨的描述,上面是一个例子

  • 后续讲解时,以简明直白为目标,不会总以上面的方式来描述算法

java实现

public static int binarySearch(int[] a, int target) {
    int i = 0, j = a.length - 1;
    while (i <= j) {
        int m = (i + j) / 2;
        if (target < a[m]) {            // 在左边
            j = m - 1;
        } else if (a[m] < target) {     // 在右边
            i = m + 1;
        } else {
            return m;
        }
    }
    return -1;
}

java 实现(基础优化版)

public static int binarySearch(int[] a, int target) {
    int i = 0, j = a.length - 1;
    while (i <= j) {
        int m = (i + j) >>> 1;
        if (target < a[m]) {            // 在左边
            j = m - 1;
        } else if (a[m] < target) {     // 在右边
            i = m + 1;
        } else {
            return m;
        }
    }
    return -1;
}
  • $i,j$ 对应着搜索区间 $[0,a.length-1]$(注意是闭合的区间),$i<=j$ 意味着搜索区间内还有未比较的元素,$i,j$ 指向的元素也可能是比较的目标

    • 思考:如果不加 $i==j$ 行不行?

    • 回答:不行,因为这意味着 $i,j$ 指向的元素会漏过比较

  • $m$ 对应着中间位置,中间位置左边和右边的元素可能不相等(差一个),不会影响结果

  • 如果某次未找到,那么缩小后的区间内不包含 $m$

2) 改变版

另一种写法

public static int binarySearch(int[] a, int target) {
    int i = 0, j = a.length;
    while (i < j) {
        int m = (i + j) >>> 1;
        if (target < a[m]) {            // 在左边
            j = m;
        } else if (a[m] < target) {     // 在右边
            i = m + 1;
        } else {
            return m;
        }
    }
    return -1;
}
  • i,j 对应着搜索区间 [0,a.length)(注意是左闭右开的区间),i<j 意味着搜索区间内还有未比较的元素,j 指向的一定不是查找目标

    • 思考:为啥这次不加 i==j 的条件了?

    • 回答:这回 $j$ 指向的不是查找目标,如果还加 $i==j$ 条件,就意味着 $j$ 指向的还会再次比较,找不到时,会死循环

  • 如果某次要缩小右边界,那么 $j=m$,因为此时的 m 已经不是查找目标了

0

评论区