001查找算法之二分查找法

你可以从这篇文章学到如下东西:

  • 线性查找的一个大致介绍
  • 二分查找的大致情况
  • 二分查找的java代码实现
  • 主页也有很多算法的一些知识,可以参一下

一、线性查找算法

由于这个过于简单就不分析了

package cn.mldn;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class searchSort {
    public static void main(String[] args) {
        int[] arr = {1,9,-1,34,89,1};
        System.out.println(arr[seqSearch1(arr, 1)]);
        //测试查找多个
        List<Integer> list = seqSearch2(arr,1);
        //不懂下面的输出的话就去找Iterator了解一下
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }


    //线性查找的方法
    public static int seqSearch1(int[] arr,int value) {
        //线性查找是逐一比较,然后返回
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value) {
                return i;
            }
        }
        return -1;
    }

    //线性查找返回多个
    public static List<Integer> seqSearch2(int[] arr, int value) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value) {
                list.add(i);
            }
        }
        return list;
    }
}

二、二分查找

1、二分查找介绍

二分查找只能针对有序数组进行二分查找{1,8,89,1000,1234}(所有在这就之前学习的排序算法可以用上了),输入一个数康康该数组是否存在此数,并且求出下标,如果没有就提示提示没有这个数。

2、二分查找分析

其实就是递归查找(也有非递归版,不过在这暂时不写),既然用上了递归,所有千千万万不要忘记咱们递归的思想,不能忘记给结束条件,思路分析如下:

  • 首先找到中间数组的下标mid = (reft + right) / 2

  • 然后让要查找的数mid下标的数比较,findVal 与 arr[mid]比较

    • findVal > arr[mid]向右查找,即向右递归
    • findVal < arr[mid]向左查找,即向右递归
    • findVal = arr[mid]说明找到了,即返回即可
  • 结束的条件

    • 找到就结束递归
    • 递归完了整个数组也结束递归 left > right

3、代码实现

(1)优坑版

1、代码

package cn.mldn;


public class BinarySearch {
    public static void main(String[] args) {
        //注意啊,数组必须是有序的
        int[] arr = {1,8,10,29,100,1234};
        int i = binarySearch(arr, 0, arr.length - 1, 1234);
        System.out.println(i);
    }


    /**
     *
     * @param arr 数组
     * @param left 左边的索引
     * @param right 右边的索引
     * @param findVal 要查找的值
     * @return 找到就返回响应的值,没有就返回-1
     */
    //二分查找
    public static int binarySearch(int[] arr,int left,int right,int findVal) {
        int mid = (left + right) / 2;//中间索引
        int midVal = arr[mid];//
        //向右递归
        if (findVal > midVal) {
            return binarySearch(arr,mid + 1,right,findVal);
        } else if (findVal < midVal) {//像左递归,注意理解的啊
            return binarySearch(arr,left,mid - 1,findVal);
        } else {
            return mid;
        }

    }
}

2、报错格式

在这里插入图片描述
3、分析原因

我找了一个数组里面没有的数据44,原因是我们没有考虑它死递归的情况

(2)没坑版

当我们的左边索引left打于right后,说明有问题了,因为left在增加而right在减少

package cn.mldn;


public class BinarySearch {
    public static void main(String[] args) {
        //注意啊,数组必须是有序的
        int[] arr = {1,8,10,29,1000,1234};
        int i = binarySearch(arr, 0, arr.length - 1, 44);
        System.out.println(i);
    }


    /**
     *
     * @param arr 数组
     * @param left 左边的索引
     * @param right 右边的索引
     * @param findVal 要查找的值
     * @return 找到就返回响应的值,没有就返回-1
     */
    //二分查找
public static int binarySearch(int[] arr,int left,int right,int findVal) {
        int mid = (left + right) / 2;//中间索引
        int midVal = arr[mid];//
        if (left > right) {//如果都没有找到就返回-1
            return -1;
        }
        //向右递归
        if (findVal > midVal) {
            return binarySearch(arr,mid + 1,right,findVal);
        } else if (findVal < midVal) {//像左递归,注意理解的啊
            return binarySearch(arr,left,mid - 1,findVal);
        } else {
            return mid;
        }
    }

4、分析课后思考题

{1,8,10,29,1000,1000,1234};当一个数组里面中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的1000.

(1)来看一下之前的编写

以我们之前写的代码测试的话得到如下结果

在这里插入图片描述

(2)代码实现

package cn.mldn;


import java.util.ArrayList;
import java.util.List;

public class BinarySearch {
    public static void main(String[] args) {
        //注意啊,数组必须是有序的
        int[] arr = {1,8,10,29,1000,1000,1234};
        List<Integer> i = binarySearch2(arr, 0, arr.length - 1, 1000);
        System.out.println(i);
    }


    /**
     *
     * @param arr 数组
     * @param left 左边的索引
     * @param right 右边的索引
     * @param findVal 要查找的值
     * @return 找到就返回响应的值,没有就返回-1
     */
    //二分查找
    public static int binarySearch(int[] arr,int left,int right,int findVal) {
        int mid = (left + right) / 2;//中间索引
        int midVal = arr[mid];//
        if (left > right) {//如果都没有找到就返回-1
            return -1;
        }
        //向右递归
        if (findVal > midVal) {
            return binarySearch(arr,mid + 1,right,findVal);
        } else if (findVal < midVal) {//像左递归,注意理解的啊
            return binarySearch(arr,left,mid - 1,findVal);
        } else {
            return mid;
        }
    }

    //问题思路分析 int[] arr = {1,8,10,29,1000,1000,1234};
        //1、在找到mid索引值,不要马上返回
        //2、向mid索引的右边扫描,将所有的满足1000的元素下标,加入到集合ArrayList中
        //3、向mid索引的左边扫描,将所有的满足1000的元素下标,加入到到集合中
    public static List<Integer> binarySearch2(int[] arr, int left, int right, int findVal) {
        int mid = (left + right) / 2;//中间索引
        int midVal = arr[mid];//

        List<Integer> list = new ArrayList<>();//定义返回的数组

        if (left > right) {//如果都没有找到就返回-1
            list.add(-1);
        }
        //向右递归
        if (findVal > midVal) {
            return binarySearch2(arr,mid + 1,right,findVal);
        } else if (findVal < midVal) {//像左递归,注意理解的啊
            return binarySearch2(arr,left,mid - 1,findVal);
        } else {
            //向mid索引的左边进行扫描,将所有的1000的元素的下标加入到集合ArrayList里面
            int temp = mid - 1;//mid的左边部分的最右边一个的索引
            while (true) {
                if (temp < 0 || arr[temp] != findVal) {//说明没有找到退出
                    break;
                }
                //否则就把temp放到集合里面
                list.add(temp);
                temp -= 1;
            }
            list.add(mid);//中间部分添加到里面
            //向mid索引的右边进行扫描,将所有的1000的元素的下标加入到集合ArrayList里面
            temp = mid + 1;//同样的道理好好理解
            while (true) {
                if (temp > 0 || arr[temp] != findVal) {//说明没有找到退出
                    break;
                }
                //否则就把temp放到集合里面
                list.add(temp);
                temp += 1;//向右移动
            }
            return list;
        }
    }
}

测试一下:
在这里插入图片描述

5、一些小建议

其实啊,如果你们看到这里的话,我建议各位能用泛型去试一下这部分代码的实现。(包括看我主页的其他算法和数据结构的都可以自己用泛型来实现一下)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值