二分法的应用

请添加图片描述

文章目录

  • 什么是二分法🎮
  • 二分查找的优先级
  • 二分查找的步骤💥
    • 图解演示🧩
  • 代码演示🫕
    • python程序实现🐈‍⬛
    • C程序实现🐕‍🦺
    • C++程序实现🐯
    • Java程序实现🐳
  • 非常规类二分查找🏡
    • 查找有序列表中某数首次出现的位置🫖

什么是二分法🎮

二分法(Bisection method),即一分为二的的方法。数学的零点估计问题中:对于在区间[a,b]上连续不断且满足 f(a) * f(b) <0的函数y=f(x),通过不断地把函数f(x)的零点所在区间二等分,使区间两个端点逐步逼近零点,进而得到零点的近似值的方法。

😎当然,在我们技术人的手中,一般是用来解决有序列表中查找某个元素的问题,属于搜索方法的一种。
😵‍💫简单的来说,就是将答案所在的区间不断缩小为原来的 1/2,直到找到答案。

🎉类似二分法的实例
假如你和朋友在玩猜数字游戏,朋友记录一个数,规定数的范围,你来猜。你每猜一个数,朋友会告诉你这个数大了还是小了,直到你猜出正确答案为止。假如有100个数,你一个一个数猜,你最差的情况需要找100次,如果你使用二分的思想查找,每次折半,最多只需要7次即可猜出答案。

二分查找的优先级

二分查找算法的时间复杂度为O(log n),因此其优先级较高,适合在需要快速查找有序列表中的元素时使用。相比于线性查找算法的时间复杂度为O(n),二分查找算法具有更高的效率,尤其适用于数据量较大的情况。同时,二分查找算法较为简单,易于实现和理解,因此被广泛应用于各个领域的程序设计中。
二分查找的效率虽然高,但只局限于有序列表

二分查找的步骤💥

二分查找的思路是先取中间位置的值进行比较,如果该值等于目标值,则查找成功;否则,如果该值大于目标值,则在左半部分继续查找;如果该值小于目标值,则在右半部分继续查找。不断重复以上步骤,直到找到目标值或者确定目标值不存在为止。

图解演示🧩

在下面这个有序数组中查找数字3
定义三个指针:left、right、mid
这三个指针都是动态的,left 为左边界的下标,right 为右边界的下标,mid=(left+right)/2

在这里插入图片描述
arr[mid]>3,中间值大于目标值,说明右边没有要查找的数,之后范围缩小到左边。
改变右指针right=mid-1在这里插入图片描述
这里 arr[mid] 恰好等于要查找的数,二分结束。
假设要查找的数变为4,那么还需要继续查找,如图在这里插入图片描述
arr[mid]<4,中间值小于目标值,说明左边没有要查找的数,范围再缩小到原来的右边
改变左指针left=mid+1
在这里插入图片描述
arr[mid]=4 就找到了需要查找的数
当左指针 left 大于等于右指针 right 时,二分查找结束,答案可能是找到目标值或者目标值不存在。

代码演示🫕

其中,arr为有序列表,target为需要查找的元素,最终未找到就返回 -1

python程序实现🐈‍⬛

def binary_search(arr, target):left, right = 0, len(arr) - 1while left <= right:mid = (left + right) // 2if arr[mid] == target:return midelif arr[mid] < target:left = mid + 1else:right = mid - 1return -1

定义一个函数binary_search,该函数接受两个参数:一个有序数组 arr 和要查找的目标元素 target

C程序实现🐕‍🦺

#include <stdio.h>// 二分查找函数
int binary_search(int arr[], int left, int right, int target){while (left <= right) // 当left>right时停止查找{int mid = (left + right) / 2; // 计算中间位置if (arr[mid] == target) // 找到目标值{return mid;}else if (arr[mid] < target) // 目标值在右半部分{left = mid + 1;}else // 目标值在左半部分{right = mid - 1;}}return -1; // 没有找到目标值
}int main()
{int arr[] = {1, 3, 5, 7, 9, 11}; // 有序数组int n = sizeof(arr) / sizeof(arr[0]); // 数组长度int target = 5; int index = binary_search(arr, 0, n - 1, target); // 进行二分查找if (index == -1){printf("目标值不存在\n");}else{printf("目标值在数组中的下标为:%d\n", index);}return 0;
}

自己定义一个函数binary_search,接收数组、数组的左右边界下标(或数组元素个数),以及要查找的元素

C++程序实现🐯

#include <iostream>
using namespace std;int binarySearch(int arr[], int l, int r, int x) {if (r >= l) {int mid = l + (r - l) / 2;if (arr[mid] == x) {return mid;}if (arr[mid] > x) {return binarySearch(arr, l, mid - 1, x);}return binarySearch(arr, mid + 1, r, x);}return -1;
}int main() {int arr[] = { 2, 4, 6, 8, 10 };int n = sizeof(arr) / sizeof(arr[0]);int x = 8;int result = binarySearch(arr, 0, n - 1, x);if (result == -1) {cout << "Element not found" << endl;}else {cout << "Element found at index " << result << endl;}return 0;
}

函数binarySearch为二分查找函数,该函数接受一个整数数组,数组的左右边界以及要查找的元素

Java程序实现🐳

public class BinarySearch {int binarySearch(int arr[], int l, int r, int x) {if (r >= l) {int mid = l + (r - l) / 2;if (arr[mid] == x) {return mid;}if (arr[mid] > x) {return binarySearch(arr, l, mid - 1, x);}return binarySearch(arr, mid + 1, r, x);}return -1;}public static void main(String args[]) {BinarySearch bs = new BinarySearch();int arr[] = { 2, 4, 6, 8, 10 };int n = arr.length;int x = 8;int result = bs.binarySearch(arr, 0, n - 1, x);if (result == -1) {System.out.println("Element not found");}else {System.out.println("Element found at index " + result);}}
}

在此示例中定义了一个类BinarySearch,其中包含一个递归函数binarySearch,该函数接受一个整数数组,数组的左右边界以及要查找的元素。

非常规类二分查找🏡

查找有序列表中某数首次出现的位置🫖

如下图中,找到3首次出现的位置(左边界),不难。但要以时间复杂度为 log(N)找到,就要采用二分查找了。
在这里插入图片描述
C程序代码

int Find_Edges(int*nums,int len,double k)
{int left=0,right=len-1;while(left<=right){int mid=(left+right)/2;if(nums[mid]<k)left=mid+1;else if(nums[mid]>k)right=mid-1;}return left;
}int GetNumberOfK(int* nums, int numsLen, int k ) {return Find_Edges(nums,numsLen,k-0,5);
}

上面这段代码将参数 3-0.5 传上去,就可以求出3的左边界,因为传上去的是浮点数,那肯定是找不到的,只能找到距离最近的向上取整的可以找到的数,因为整数除法是向下取整的,所以,mid的值一定是小于等于 (left+right)/2的,所以一定会在 left 位置结束二分查找。

同样,将参数 3+0.5 传上去,就可以求出3的右边界,进而求出这个数组中一共有多少个3,进而解决这篇博客中最后一题C语言笔试训练。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电源控制--条件稳定

控制系统的条件稳定是指系统在一定条件下能够保持稳定性的特性。稳定性是控制系统设计中非常重要的概念&#xff0c;它涉及系统的输出在时间上是否趋向于有限值或者周期性变化&#xff0c;而不是无限增长或发散。 在控制系统中&#xff0c;条件稳定的要求通常涉及到以下几个方…

Sentieon|应用教程:利用Sentieon Python API引擎为自研算法加速

背景 Sentieon套装中所有模块的速度都远超对应开源软件的数倍至数十倍&#xff0c;用户在使用这些模块的同时&#xff0c;有时也希望Sentieon团队可以帮助加速自己开发的定制化软件。为了帮助这些用户能在自研软件上享受到Sentieon模块的速度&#xff0c;我们开发了Python API…

【深度学习MOT】SMILEtrack SiMIlarity LEarning for Multiple Object Tracking,论文

论文&#xff1a;https://arxiv.org/abs/2211.08824 文章目录 AbstractIntroduction2. 相关工作2.1 基于检测的跟踪2.1.1 检测方法2.1.2 数据关联方法 2.2 基于注意力的跟踪 3. 方法3.1 架构概述3.2 用于重新识别的相似性学习模块&#xff08;SLM&#xff09; Experimental Res…

【Python机器学习】实验08 决策树

文章目录 决策树1 创建数据2 定义香农信息熵3 条件熵4 信息增益5 计算所有特征的信息增益&#xff0c;选择最优最大信息增益的特征返回6 利用ID3算法生成决策树7 利用数据构造一颗决策树Scikit-learn实例决策树分类决策树回归Scikit-learn 的决策树参数决策树调参 实验1 通过sk…

【C++】string的使用

1、string的使用 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include<string> using namespace std;void Test1() {string s1;string s2("hello");cin >> s1;cout << s1 << endl;//strcat【字符串拼接】string ret1 s…

【solon生态】- solon.cloud.micrometer插件使用指南及micrometer详解

solon.cloud.micrometer插件使用指南 solon是什么solon的cloud生态图快速入门 micrometer指南micrometer是什么监控系统 Supported Monitoring Systems注册表 Registry度量 Meters度量名 Naming Meters度量标签 Tag Naming通用标签 Common Tags 指标过滤器 MeterFilter聚合速率…

月报总结|Moonbeam 7月份大事一览

炎炎夏日&#xff0c;Moonbeam于越南举办了线下交流会&#xff0c;在EthCC 2023和以太坊社区成员共同讨论多链应用&#xff0c;在Polkadot Decoded中分享了Moonbeam的与众不同之处。 Bear Necessities Hackathon也于本月圆满结束&#xff0c;选出了每个赛道最杰出的项目&#…

JS逆向系列之猿人学爬虫第8题-验证码-图文点选

题目地址 https://match.yuanrenxue.cn/match/8本题的难点就在于验证码的识别,没啥js加密,只要识别对了携带坐标就给返回数据 回过头来看验证码 这里复杂的字体比较多,人看起来都有点费劲(感觉可能对红绿色盲朋友不太又好)&#x

redis原理 1:鞭辟入里 —— 线程 IO 模型

Redis 是个单线程程序&#xff01;这点必须铭记。 也许你会怀疑高并发的 Redis 中间件怎么可能是单线程。很抱歉&#xff0c;它就是单线程&#xff0c;你的怀疑暴露了你基础知识的不足。莫要瞧不起单线程&#xff0c;除了 Redis 之外&#xff0c;Node.js 也是单线程&#xff0c…

iPhone手机怎么恢复出厂设置(详解)

如果您的iPhone遇到了手机卡顿、软件崩溃、内存不足或者忘记手机解锁密码等问题&#xff0c;恢复出厂设置似乎是万能的解决方法。 什么是恢复出厂设置&#xff1f;简单来说&#xff0c;就是让手机重新变成一张白纸&#xff0c;将手机所有数据都进行格式化&#xff0c;只保留原…

C++结构体部分显式构造导致编译异常分析

今天调试了一段代码如下 #include <iostream> #include <shared_mutex>#define SECT_NUM 2 #define DI_HIGH_PERM 2 #define DI_READ 1 #define DI_WRITE 2 #define FMT_BIN 1#define USER_PATH "d:\\fafiles\\dbtest\\"typedef unsigned long DW…

Python 之禅

Python 社区的理念都包含在 Tim Peters 撰写的 “Python 之禅” 中 在 Windows 平台的 cmd 命令中打开 python&#xff0c;输入 import this&#xff0c;就能看到 Python 之禅: 翻译&#xff1a; Tim Peters 的 python 之禅Beautiful is better than ugly. # 优美胜于丑陋&am…

鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统em

​ Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目…

chapter13:springboot与任务

Spring Boot与任务视频 1. 异步任务 使用注解 Async 开启一个异步线程任务&#xff0c; 需要在主启动类上添加注解EnableAsync开启异步配置&#xff1b; Service public class AsyncService {Asyncpublic void hello() {try {Thread.sleep(3000);} catch (InterruptedExcept…

vue3 动态导入src/page目录下的所有子文件,并自动注册所有页面组件

main.js添加一下代码&#xff1a; const importAll (modules) > {Object.keys(modules).forEach((key) > {const component key.replace(/src/, /).replace(.vue, );const componentName key.split(/).slice(-2, -1)[0] -page;app.component(componentName, modules…

Asynq: 基于Redis实现的Go生态分布式任务队列和异步处理库

Asynq[1]是一个Go实现的分布式任务队列和异步处理库&#xff0c;基于redis&#xff0c;类似Ruby的sidekiq[2]和Python的celery[3]。Go生态类似的还有machinery[4]和goworker 同时提供一个WebUI asynqmon[5]&#xff0c;可以源码形式安装或使用Docker image, 还可以和Prometheus…

网络基本概念

目录 一、IP地址 1. 概念 2. 格式 3. 特殊IP 二、端口号 1.概念 2. 格式 3.注意事项 三、 协议 1. 概念 2. 作用 四、协议分层 1. 网络设备所在分层 五、封装与分用 六、客户端和服务器 1. 客户端与服务器通信的过程 一、IP地址 1. 概念 IP地址主要用于标识网络主机.其他网络…

如何搭建个人的GPT网页服务

写在前面 在创建个人的 GPT网页之前&#xff0c;我登录了 Git 并尝试了一些开源项目&#xff0c;但是没有找到满足我个性化需求的设计。虽然许多收费的 GPT网页提供了一些免费额度&#xff0c;足够我使用&#xff0c;但是公司的安全策略会屏蔽这些网页。因此&#xff0c;我决定…

机器视觉、图像处理和计算机视觉:概念和区别

机器视觉、图像处理和计算机视觉是相关但有区别的概念。 机器视觉主要应用于工业领域&#xff0c;涉及图像感知、图像处理、控制理论和软硬件的结合&#xff0c;旨在实现高效的运动控制或实时操作。 图像处理是指利用计算机对图像进行复原、校正、增强、统计分析、分类和识别…

Linux 1.2.13 -- IP分片重组源码分析

Linux 1.2.13 -- IP分片重组源码分析 引言为什么需要分片传输层是否存在分段操作IP分片重组源码分析ip_createip_findip_frag_createip_doneip_glueip_freeip_expireip_defragip_rcv 总结 本文源码解析参考: 深入理解TCP/IP协议的实现之ip分片重组 – 基于linux1.2.13 计网理论…