数据结构与算法系列十八(二分查找)

183 阅读4分钟

前面我们通过一系列分享,相信你已经掌握了常用的排序算法思想和代码实现,你还记得它们吗?让我们一起来简单回顾一下:冒泡排序、插入排序、选择排序、归并排序、快速排序、桶排序、计数排序。我们一共分享了七个常见的排序算法。

接下来我们通过两篇文章分享一个以排序为基础的算法:二分查找。二分查找是一个高效的查找算法,它的时间复杂度是:O(logn)那具体什么是二分查找呢?

让我们一起来玩一个游戏,通过游戏,相信你很快就能理解二分查找了:

1.今天正好是周末,你们几个朋友在家没有什么事做,有人提议玩猜字游戏

2.具体游戏规则是这样的:

  • 0-49个数字中,任意选择一个目标数字,比如:9
  • 当然目标数字,在答案揭晓前,是需要隐藏起来的(只能你看见,不能让你的朋友看见)
  • 然后你的朋友开始猜字,每次猜测,你只需要告诉朋友:比目标数字大了,或者小了,或者猜中了(揭晓答案)

3.问题:

  • 你的朋友要如何猜测,能在最短的时间内,猜中目标数字?
#考考你:
1.你知道二分查找的核心思想吗?
2.你能用java实现二分查找吗?

案例

二分查找核心思想

我们还是以上面的猜字游戏为基础,来分析二分查找的核心思想。游戏背景是:

1.有0-49个数字,任意从中选择一个数字,作为目标数字,比如:9

2.如何在最短的时间内,猜中目标数字:9

image.png

二分查找核心思想:

1.第一次,选择0-49范围内的中间数字,比如(0+49)/2=24
2.将中间数字24,与目标数字9比较,得出:24>9
3.第二次,将数据查找范围减半,由于第一次的24>9,第二次选择:0-23的范围
4.选择0-23范围内的中间数字,比如:(0+23)/2=11
5.将中间数字11,与目标数字9进行比较,得出:11>9
6.以此类推,每次将数据范围减半(折半查找==二分查找).......
7.分析到这里,你应该已经理解了二分查找的核心思想:每一次将数据范围减半,查找目标数字,能够在最短的时间内,找到目标数字

二分查找代码实现

循环实现

package com.anan.algorithm.search;

import java.util.Arrays;

/**
 * 二分查找,循环实现
 */
public class BinarySearchWhile {

    public static void main(String[] args) {

        // 排好序的数组(二分查找的前提)
        int[] array = {1,3,5,7,9,10,12,14,16,17,18,19};
        // 目标值
        int target = 9;
        System.out.println("1.有序数组:"+ Arrays.toString(array));
        System.out.println("2.查找目标数字:" + target);

        // 开始二分查找
        System.out.println("-------------------------开始二分查找------------------------");
        int index = binarySearch(array,array.length,target);
        System.out.println("3.查找目标值:" + target + ",在数组中的下标索引:" + index);

    }

    /**
     * 二分查找
     * @param array  数据集合(数组)
     * @param n   数据规模
     * @return
     */
    public static int binarySearch(int[] array,int n,int target){
        int result = -1;

        // 定义下标标记索引
        int low = 0;
        int high = n - 1;
        while (low <= high){
            int mid = (low + high) / 2;
            if(array[mid] == target){
                return mid;
            }else if(array[mid] < target){
                low = mid + 1;
            }else {
                high = mid - 1;
            }

        }

        return result;
    }
}

image.png

递归实现

package com.anan.algorithm.search;

import java.util.Arrays;

/**
 * 二分查找,递归实现
 */
public class BinarySearchRecursion {

    public static void main(String[] args) {
        // 排好序的数组(二分查找的前提)
        int[] array = {1,3,5,7,9,10,12,14,16,17,18,19};
        // 目标值
        int target = 9;
        System.out.println("1.有序数组:"+ Arrays.toString(array));
        System.out.println("2.查找目标数字:" + target);

        // 开始二分查找
        System.out.println("-------------------------开始二分查找------------------------");
        int index = binarySearch(array,array.length,target);
        System.out.println("3.查找目标值:" + target + ",在数组中的下标索引:" + index);
    }


    /**
     * 二分查找入口(递归实现)
     */
    public static int binarySearch(int[] array,int n,int target){

        return recursionBinarySearch(array,0,n - 1,target);
    }

    /**
     * 二分查找递归
     * @param array  目标数组
     * @param low   查找范围低位
     * @param high  查找范围高位
     * @param target  目标值
     * @return
     */
    public static int recursionBinarySearch(int[] array,int low,int high,int target){
        // 递归终止条件
        if(low > high){
            return  -1;
        }

        // 计算中位数
        int mid = low + ((high - low) >>1);
        if(array[mid] == target){
            return mid;
        }else if(array[mid] < target){
            return recursionBinarySearch(array,mid + 1,high,target);
        }else{
            return recursionBinarySearch(array,low, mid - 1,target);
        }
    }
}

image.png

讨论分享

#考考你答案:
1.你知道二分查找的核心思想吗?
	二分查找核心思想
2.你能用java实现二分查找吗?
	二分查找代码实现
	
3.思考题:
  1.二分查找的代码实现比较简单,很容易理解
  2.请你先思考:二分查找的代码实现,需要注意的细节事项
  3.请你先思考:如果目标数组中,有重复的数字,二分查找该如何实现呢?
  【以上思考问题】:我们将在下一篇分享中讨论