Java查找算法:二分法查找

思路

二分法查找的目标数组必须为有序数组,以一个从小到大排列的数组为例:

  1. 首先确定该数组的中间下标mid = (left + right) / 2
  2. 然后用查找目标数targetVal和arr[mid]比较
    1. targetVal > arr[mid],查找的目标数在mid右边
    2. targetval < arr[mid],查找的目标数在mid左边
    3. targetVal = arr[mid],找到目标数

代码

示例包括使用递归二分法和wile循环二分法,支持查找多个目标数

package com.leolee.dataStructure.search;

import java.util.HashSet;
import java.util.Set;

/**
 * @ClassName BinarySearch
 * @Description: 二分法查找(查找的数组为有序的)
 * 思路,以一个从小到大的数组为例:
 * 1.首先确定确定该数组的中间下标mid=(left+right)/2
 * 2.然后用目标数targetVal与arr[mid]比较
 *  2.1targetVal > arr[mid] 查找的目标数在mid的右边
 *  2.2target = arr[mid] 查找的目标数找到
 *  2.2targetVal < arr[mid] 查找的目标数在mid的左边
 * 什么时候结束递归:
 *  1)找到就结束递归
 *  2)递归查询了整个数组,仍找不到目标数,当left > right退出
 * @Author LeoLee
 * @Date 2020/11/1
 * @Version V1.0
 **/
public class BinarySearch {


    /*
     * 功能描述: <br>
     * 〈二分查找〉查找目标数组只存在一个目标数,递归方式
     * @Param: [arr 查找目标数组, left, right, targetval 目标数]
     * @Return: int 目标数的下标,不存在返回-1
     * @Author: LeoLee
     * @Date: 2020/11/1 14:45
     */
    public static int search(int[] arr, int left, int right, int targetval) {

        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (left > right) {
            return -1;
        }
        if (targetval > midVal) {//向右递归
            return search(arr, mid + 1, right, targetval);
        } else if (targetval < midVal) {//向左递归
            return search(arr, left, mid - 1, targetval);
        } else if (targetval == midVal) {
            return mid;
        }
        return -1;
    }


    /*
     * 功能描述: <br>
     * 〈二分查找〉查找目标数组只存在一个目标数, while方式
     * @Param: [arr 查找目标数组, left, right, targetval 目标数]
     * @Return: int 目标数的下标,不存在返回-1
     * @Author: LeoLee
     * @Date: 2020/11/1 14:45
     */
    public static int search(int[] arr, int targetval) {

        int left = 0;
        int right = arr.length - 1;
        int mid = 0;

        while (!(left > right)) {
            mid = (left + right) / 2;
            if (targetval > arr[mid]) {
                left = mid + 1;
            } else if (targetval < arr[mid]) {
                right = mid -1;
            } else {
                return mid;
            }
        }

        return -1;
    }


    /*
     * 功能描述: <br>
     * 〈二分查找〉支持目标数组存在多个目标数
     *  在找到目标数之后不要马上返回
     * @Param: [arr 查找目标数组, left, right, targetval 目标数]
     * @Return: int 目标数的下标,不存在返回-1
     * @Author: LeoLee
     * @Date: 2020/11/1 15:00
     */
    public static Set search2(int[] arr, int targetval) {

        int left = 0;
        int right = arr.length - 1;
        int mid = 0;
        Set set = new HashSet();

        while (!(left > right)) {
            mid = (left + right) / 2;
            if (targetval > arr[mid]) {
                left = mid + 1;
            } else if (targetval < arr[mid]) {
                right = mid -1;
            } else {
                //在找到目标数之后不要马上返回
                //分别向mid左右两边扫描,将所有与arr[mid]相同的数全部找出来放入集合
                int temp = mid - 1;
                while (true) {
                    //退出条件
                    if (temp < 0 || arr[temp] != targetval) {
                        break;
                    }
                    set.add(temp);
                    temp-=1;
                }

                temp = mid + 1;
                while (true) {
                    //退出条件
                    if (temp > arr.length -1 || arr[temp] != targetval) {
                        break;
                    }
                    set.add(temp);
                    temp+=1;
                }

                set.add(mid);
                break;
            }
        }
        return set;
    }


    public static void main(String[] args) {

        int[] arr = {1, 8, 10, 89, 1000, 1234};
        System.out.println(BinarySearch.search(arr, 0, arr.length - 1, 8));
        System.out.println(BinarySearch.search(arr, 8));

        int[] arr2 = {1, 8, 10, 89, 1000, 1000, 1234};
        BinarySearch.search2(arr2, 1000).forEach(e -> {
            System.out.print(e + ",");
        });

    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值