折半查找算法[二分查找法]算法的实现和解决整数溢出问题~

news2024/11/28 16:52:41

算法实现的要求:

折半查找法又称为二分查找法,这种方法对待查找的列表有两个要求:

1:必须采用顺序存储结构
2:必须按关键字大小有序排列

算法思想:

将表中间位置记录的关键字与查找关键字进行比较如果两者相等,则查找成功,否则利用中间位置记录将表分成前后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表

重复上述查找过程,直到找到满足条件的记录,则查找成功,或直到子表不存在为止,则查找不成功

使用java实现该算法:

算法实现方法:

1:前提要求:有已排序数组A[因为在查找的过程中是根据下标进行的]

2:定义左边界L,右边R,确定搜索范围,循环执行二分查找

3:获取中间索引M=(L+R)/2,如果是小数,一般默认向下取整

4:中间索引的值A[M]与带搜索的值T进行比较
A[M]==T,返回中间索引
A[M]>T,中间值右侧的其他元素都大于T,无需比较,中间索引左边去找,M-1,设置为右边界,重新查找
A[M]<T,中间值左侧的其他元素都小于T,无需比较,中间索引右边去找,M+1设置为左边界,重新查找

5:当L>R时,表示没有找到,应结束循环

代码如下所示:

package bin_find;

import java.util.Scanner;

public class bin_find {
    public static void main(String[] args) {
        int arr[] = {4, 10, 18, 23, 45, 68, 199};
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你要查找的数:");
        int x = scanner.nextInt();
        int result= bin_research(arr,x);
        if(result!=-1){
            System.out.println("你要查找的数已找到,它是数组的第"+(result+1)+"个元素");
        }
        else{
            System.out.println("你要查找的数不存在");
        }
    }

    public static int bin_research(int arr[], int x) {
        int L = 0;
        int R = arr.length - 1;
        while(L<=R) {
        //不要写到循环外面了,因为每查找一次,中间索引的位置也需要变化
            int M = (L + R) / 2;
            if (x > arr[M]) {
                L = M+1;
            } else if (x < arr[M]) {
                R = M - 1;
            } else if (x == arr[M]) {
                return M;
            }
        }
        return -1;
    }
}

输出:

请输入你要查找的数:
23
你要查找的数已找到,它是数组的第4个元素

整数溢出现象:

package bin_find;

public class bin_find2 {
    public static void main(String[] args) {
        int l=0;
        int r=Integer.MAX_VALUE-1;
        int m=(l+r)/2;
        //当要查找的数在左子表时:
        System.out.println(m);
        //当要查找的数在右子表时:发生整数溢出现象
        l=m+1;
        m=(l+r)/2;
        System.out.println(m);
    }
}

输出:

1073741823
-536870913

之所以会出现负数的原因:是因为在计算机中,是根据二进制进行运算的,逢二进一,由于最高位表示符号位,当它为1时,该数即为负数!

对该过程不熟悉的小伙伴,可以去看我写的这篇文章

解决整数溢出问题:

上述代码中产生溢出的原因是由于:当要查找的数在右子表时,此时:r最初为整数的最大值-1不变,而l的值增大到了r/2的大小,因此即使他两相加除2,在计算机中,是根据二进制进行运算的,逢二进一,由于最高位表示符号位,当它为1时,该数即为负数,那么解决溢出的核心就是改变m的值,但所谓的改变,并不是将m的值真正的改变,而是通过变换表达式等等,去调整m的大小

方法1:通过调整数学表达式

方法如下:

在这里插入图片描述

代码如下:

package bin_find;

public class bin_find2 {
    public static void main(String[] args) {
        int l=0;
        int r=Integer.MAX_VALUE-1;
        int m=l+(r-l)/2;
        //当要查找的数在左子表时:
        System.out.println(m);
        //当要查找的数在右子表时:
        l=m+1;
        m=l+(r-l)/2;
        System.out.println(m);
    }
}

输出:

1073741823
1610612735

方法2:通过>>>运算符

>>>表示无符号右移运算符也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0,移动的是二进制位,但他们的操作数必须是整数,[当被操作的数是整数时]右移一位有除二的效果,因此对于上述溢出现象,右移一位既能够避免最高位[符号位]为1,导致该数为负数的现象,而且正好借用它右移一位有除二的效果,还简化了数学表达式;

修改如下:

package bin_find;

public class bin_find2 {
    public static void main(String[] args) {
        int l=0;
        int r=Integer.MAX_VALUE-1;
        int m=(r+l)>>>1;
        //当要查找的数在左子表时:
        System.out.println(m);
        //当要查找的数在右子表时:
        l=m+1;
        m=l+(r-l)>>>1;
        System.out.println(m);
    }
}

输出:

1073741823
1073741823

对于上述两种做法均可以解决整数溢出问题,不过我们更加推荐第二种,因为它的效率比较高!

练习题:

有一个有序表为 1,5,8,11,19,22,31,35,4045,89,50 当分查找值为48的结点时,查找成功需要比较的次数
[来源于:京东实习生招聘]

答案为:4次

这里需要强调的点就是:当子表的元素个数为偶数时,如果题目没有强调,那么我们默认选择靠左边的元素为中间数

使用二分法在序列 1,4,6,7,15,33,39,50,64,78,75,81,89,96 中查找元素81 时,需要经过()比较
[来源于:美团点评校招]

答案为:4次

在拥有128个元素的数组中二分查找一个数,需要比较的次数最多不超过多少次 [来源于:北京易道博识社招]

答案为:7次

方法1:
上述题目相当于为2^n=128,n的值为多少?

方法2:
使用128一直不断的除2,直到变为1,只需要计算除2的次数即可

方法3:
使用计算器,问题转变为log2^128,不过需要知道该计算机是以多少为底,下图为Windows10操作系统的计算器,以10为底

在这里插入图片描述

运算结果是整数,则该整数即为最终结果

运算结果是小数,则舍去小数部分,整数加一为最终结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/166469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

synchronized实现原理

0. 前言 造成线程安全问题的主要诱因有两点&#xff0c;一是存在共享数据(也称临界资源)&#xff0c;二是存在多个线程共同操作共享数据。因此为了解决线程安全问题&#xff0c;我们可能需要这样一个方案&#xff0c;当存在多个线程操作共享数据时&#xff0c;需要保证同一时刻…

ICV:2022年稀释制冷机全球市场规模达2.11亿美元,2028年有望出现突破点

全球前沿科技咨询机构ICV于2023年初发布了稀释制冷机&#xff08;DR&#xff09;的市场分析报告&#xff0c;ICV在报告中表示&#xff0c;2019-2015稀释制冷机的年均增长率达到8.59%以上&#xff0c;且增长率逐年上升。2022年全球稀释制冷机市场规模将达到2.11亿美元&#xff0…

从Deepmind最新成果DreamerV3启发的通用AI技术分析

一、背景 本文系个人观点&#xff1a;错漏在所难免&#xff0c;仅供参考 北京时间 1 月 12 日&#xff0c;DeepMind 官方推特发文&#xff0c;正式官宣 DreamerV3&#xff0c;这是首个能在游戏「我的世界」(Minecraft) 中不参考人类数据&#xff0c;就能从头开始收集钻石的通…

1.16中断实验

一.异常处理流程 1.异常处理流程 &#xff08;1&#xff09;保存现场&#xff08;CPU自动完成&#xff09; 将CPSR中状态保存到SPSR_<MODE>中 将CPSR寄存器的状态位T&#xff0c;改为ARM状态 根据需要&#xff0c;进制IRQ,FIQ中断&#xff0c;修改C…

java springboot 项目构建报错解决办法

这里总结了一些常见的springboot 项目构建报错及解决办法 错误: 无效的源发行版:17 错误原因 build.gradle 文件中可以通过下面两项来指定项目运行所需的jdk版本 sourceCompatibility:指定编译编译.java文件的jdk版本 targetCompatibility&#xff1a;确保class文件与target…

ARM 看门狗定时器

一、什么是看门狗、有什么用 (1) 看门狗定时器和普通的定时器并无本质区别。定时器可以设定一个时间&#xff0c;在这个时间完成之前定时器不断计时&#xff0c;时间到的时候&#xff0c;定时器会复位 CPU&#xff08;重启系统&#xff09;。 (2 )系统正常工作的时候当然不希望…

feign漫谈

feign的简单使用。 文章目录什么是feign准备工作三.如何使用3.1 定义pom文件3.2 定义配置文件及启动类注解3.3 定义feign接口什么是feign 远程调用框架 准备工作 需要nacos环境&#xff1a; 涉及到feign调用&#xff0c;就没法抛开注册中心&#xff0c;接下来我们使用主流的…

使用Python创建websocket服务端并给出不同客户端的请求

作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 使用Python创建websocket服务端&#xff0c;并给出不同客户端的请求 一、 WebSocket是啥 WebSocket 和HTTP一样&#xff0c;也是一种通…

java中的位运算符

在Java语言中&#xff0c;提供了7种位运算符&#xff0c;分别是按位与&#xff08;&&#xff09;、按位或&#xff08;|&#xff09;、按位异或&#xff08;^&#xff09;、取反(~)、左移(<<)、带符号右移(>>)和无符号右移(>>>)。位运算符是对long、i…

怎么把两个PDF合并成一个?这几种操作轻松合并

我们在工作中处理过的文件有很多&#xff0c;有时候为了工作更方便&#xff0c;我们通常需要把两个或是多个文件合并成为一个PDF文件&#xff0c;这样只需要打开这一个文件就可以查看全部内容&#xff0c;那么怎么把两个PDF合并成一个呢&#xff1f;这几种操作都可以轻松合并&a…

Dopamine-PEG-NH2氨基聚乙二醇多巴胺,材料改性用科研试剂

英 文 &#xff1a;NH2-PEG-Dopamine/Dopamine-PEG-NH2 中文&#xff1a;氨基聚乙二醇多巴胺 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用 途&#xff1a;仅供科研实验使用&#xff0c;不用于诊治 外观: 固体或粘性液体&#xff0c;取决于分子量 注意事项…

javaEE 初阶 — 文件内容的读写

文章目录数据流1. 字节流1.1 InputStream 概述1.1.1 无参数 read 的使用1.1.2 一个参数 read 的使用1.2 使用 OutputStream 写文件1.2.1 对于关闭文件的解释2. 字符流2.1 Reader 概述2.1.1 read 方法的使用2.2 Writer 概述2.2.1 write 的使用2.3 Scanner 补充数据流 针对文件内…

Cookie和Session以及相关的方法

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaEE 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 目录 Cookie 什么是Cookie? 为什么要用Cookie? Cookie的原理 Session 什么是Session? 为什么要用Session? Session原理 核心方法 实现用户登…

【Linux编译器】

前言 打怪升级第&#xff1a;22天 一、gcc、g 背景知识&#xff1a; gcc和g都是Linux中的编译器&#xff0c;其中gcc只可以编译C语言文件&#xff0c;g可以编译c文件&#xff0c;当然也可以编译C语言文件&#xff08;c兼容C语言嘛&#xff09;。 由于两者的操作选项基本一样&a…

转换函数和运算符类

我们以下是采用内联函数来进行的#ifndef ___Class_Counter #if 1 #endif ___Class_counter #include <climits> class Counter{unsigned cnt; // unsigned mmm; public:Counter() : cnt(0) {}//构造函数初始化器//Counter(double mmm):mmm(2){}/*void increment() {i…

低代码平台助力汽车行业构筑新基建

编者按&#xff1a;本文分析了汽车行业数字化转型的需求&#xff0c;并列举了汽车行业利用低代码平台数字化转型的场景&#xff0c;最后通过华晨汽车案例展示了低代码在实现业务模板集成方面的表现。关键词&#xff1a;数据集成&#xff0c;低代码平台&#xff0c;汽车行业汽车…

后台生成4位图像验证码

主要依赖&#xff1a; <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency>spring相关依赖参照用到的另行添加。 package com.math.controller;impor…

质心标准差和分散程度

( A, B )---1*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有1个节点&#xff0c;AB各由9张二值化的图片组成&#xff0c;在前述的实验中得到了A全是0&#xff0c;B中有3个1的迭代次数数据。 0 1 2 3 4 5 6 7 8 迭代次数 A-B 1b 1b 1b 0 0 0 0 0 0 54269.648 …

Java 日志框架 JUL

文章目录日志文件的重要性常见日志框架什么是JULJUL架构介绍入门案例JUL日志级别Logger之间的父子关系日志的配置文件日志原理解析日志文件的重要性 做开发最怕的就是线上系统出问题了&#xff0c;轻则留下产品和系统不安全可靠的不好印象&#xff0c;重则影响到公司的收入和口…

②【Spring】一文精通:IOC - 基于XML方式管理Bean

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ IOC操作&#xff1a;基于XML管理Bean一、&…