【算法学习】四 二分法查找(折半法或者折半查找)

前言

社长,一个爱学习,爱分享的程序猿,始终相信,付出总会有回报的。知识改变命运,学习成就未来。爱拼才会赢!
程序猿学社的GitHub,已整理成相关技术专刊,欢迎Star:
https://github.com/ITfqyd/cxyxs

社长,4年api搬运工程师,之前做的都是一些框架的搬运工作,做的时间越长,越发感觉自己技术越菜,有同感的社友,可以在下方留言。现更侧重于java底层学习和算法结构学习,希望自己能改变这种现状。
为什么大厂面试,更侧重于java原理底层的提问,因为通过底层的提问,他能看出一个人的学习能力,看看这个人的可培养潜力。随着springboot的流行,大部分的开发,起步就是springboot。也不看看springboot为什么简单?他底层是如何实现的。为什么同样出来4年,工资差别都很大?这些问题都值得我们深思(对社长自己说的)。
api工程师,顶天了,最多达到某些公司中级工资上限,很难突破高级这道坎。希望我们大家成就更好的自己。回想起往事,不会后悔。

目录

前言:

一 什么是二分法查找?

二 实现思路

分三种情况:

学习中遇到问题后,我们应该如何处理?

二分法查找2种实现方式

非递归方式

递归方式

性能对比分析:


一 什么是二分法查找?

二分法也可以叫折半法,他是一种一种查询效率较高的方法。适用于数据量较大时,但是需要数据先排好顺序。
小结:遇到效率高,我们就应该引起注意,就跟ArrayList一样,他的查询效率高,但是只适合于单线程,因为他线程不安全。遇到类似的问题,我们应该多反问(社长的一万个为什么),多思考。多想想,他是不是有什么缺陷或者前提。

二 实现思路

一个班的成绩有高有低,从低到高排序 50 56 60 70 80 90 92 94 98
因为是二分,每次取一般,这里先定义三个变量header mid footer,注意是对应值的下标。

分三种情况:

第一种: 相等,表示找到了。
我要找的值就是80。Mid对应的值,刚好与我要查的值相等。就没有必要继续往下走。
第二种:需要查找的值小于mid,footer=mid-1
划重点上一次的mid是4,值为80,为什么上面画的图没有80?
在第一种情况里面已经判断过,那我们为什么还需要再判断一次勒,你们说是不是这个道理。觉得对的社友扣666。
有些有着求知欲的社友,又开始问了,header为,footer为3,mid咋是1,不应该是1.5吗?
社长我也不知道为什么是1。(0+3)/2 就是1。可以先去查看一下基础。
第三种:需要查找的值大于mid,header=mid+1

学习中遇到问题后,我们应该如何处理?

我发现有不少社友都继承了社长的一万个为什么,首先,积极提出问题,这点值得表扬。社长工作也有一段时间了,遇到问题,发现,大致的人群可以分为3种。
按王者荣耀的术语做一个级别划分
第一种,不敢请教别人,怕暴露自己的真实水平,同事之间,遇到不少这种,建议,有可能你一个问题,卡了几天,别人给你一分钟指导,就帮你解决了。 青铜选手
第二种,敢于请教,但不思。 遇到问题,需要虚心的请教别人,但是,自己不多思,多查。 白银选手
第三种:多思多查敢于请教。 黄金选手

二分法查找2种实现方式

非递归方式

package com.fyqd.test.sort;

/**
 * Description:不使用递归方式
 * Author: 程序猿学社
 * Date:  2020/1/18 21:38
 * Modified By:
 */
public class BinaryTest {
    public static int binary(int[] array, int value) {
        int low = 0;
        int high = array.length - 1;
        while (low <= high) {
            int middle = (low + high) / 2;
            if (value == array[middle]) {
                return middle;
            }
            if (value > array[middle]) {
                low = middle + 1;
            }
            if (value < array[middle]) {
                high = middle - 1;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        //50 56 60 70 80 90 92 94 98
        int[] a = {50, 56, 60, 70, 80, 90, 92, 94, 98};
        int score = 60;
        int value = binary(a,score);
        if(value == -1){
            System.out.println("没有找到,继续加油!");
        }else{
            System.out.println("找到了你真棒,分数为"+score+",索引为"+value);
        }
    }
}

递归方式

package com.fyqd.test.sort;

/**
 * Description:使用递归方式
 * Author: 程序猿学社
 * Date:  2020/1/18 21:38
 * Modified By:
 */
public class BinaryTest1 {
    public static int binary(int[] array, int value) {
        int header = 0;
        int footer = array.length - 1;
        return search(array,value,header,footer);
    }

    public static int search(int[] array, int value,int header,int footer){
        if(header > footer){
            return -1;
        }

        int middle = (header + footer) / 2;

        if (value == array[middle]) {
            return middle;
        }else if (value > array[middle]) {
            header = middle + 1;
            return search(array,value,header,footer);
        }else{
            footer = footer - 1;
            return search(array,value,header,footer);
        }
    };

    public static void main(String[] args) {
        //50 56 60 70 80 90 92 94 98
        int[] a = {50, 56, 60, 70, 80, 90, 92, 94, 98};
        int score = 980;
        int value = binary(a,score);
        if(value == -1){
            System.out.println("没有找到,继续加油!");
        }else{
            System.out.println("找到了你真棒,分数为"+score+",索引为"+value);
        }
    }
}

注意:使用递归方式,一定要给出终止条件

性能对比分析:

名称 时间复杂度 空间复杂度 描述
普通排序 O(N) O(1) 通过for循环一个个查找
二分法非递归方式 O(logN) O(1)  
二分法使用递归方式 O(logN) O(1*logN) 每次调用开销1,重复调用logN次,每次需要额外的开辟空间

二分法非递归方式性能最优,为什么

《算法学习》 一:为什么要学习算法?时间复杂度

历史算法文章推荐:

《算法学习》二 冒泡排序分析

【算法学习】三 选择排序分析

后记

程序猿学社的GitHub,欢迎Star:
https://github.com/ITfqyd/cxyxs
觉得有用,可以点赞,关注,评论,留言四连发。

©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值