二分查找代码详解
二分查找代码实现
以下是完整的代码和解释:
#include <stdio.h>int binarySearch(int arr[], int length, int target) {int left = 0;int right = length - 1;while (left <= right) {int mid = left + (right - left) / 2; // 防止溢出if (arr[mid] == target) {return mid; // 找到目标元素}if (arr[mid] < target) {left = mid + 1; // 目标在右半部分} else {right = mid - 1; // 目标在左半部分}}return -1; // 未找到目标元素
}int main() {int arr[] = {1, 3, 5, 7, 9, 11};int target = 7;int length = sizeof(arr) / sizeof(arr[0]); // 在主函数中计算数组长度int result = binarySearch(arr, length, target);if (result == -1) {printf("元素未找到\n");} else {printf("元素找到了,位置为: %d\n", result);}return 0;
}
在上面的代码中,使用 int mid = left + (right - left) / 2;
代替 int mid = (left + right) / 2;
是为了防止整数溢出。具体原因和解释如下:
原因
假设 left
和 right
都是非常大的正整数,那么 left + right
可能会超过 int
类型的表示范围,导致整数溢出。然而, left + (right - left) / 2
通过先计算 (right - left) / 2
,确保了不会超过 int
的表示范围。
例子
假设 left = 2147483640
和 right = 2147483646
:
left + right
的值是4294967286
,超过了int
的最大值2147483647
,会导致溢出。right - left
的值是6
,计算(right - left) / 2
得到3
,然后left + 3
的结果是2147483643
,没有溢出。
代码执行流程
-
初始化:
left
初始化为数组的起始索引0
。right
初始化为数组的末尾索引length - 1
。
-
二分查找循环:
- 计算中间位置
mid
,使用int mid = left + (right - left) / 2;
防止溢出。 - 检查
arr[mid]
是否等于目标值target
。如果相等,返回mid
。 - 如果
arr[mid]
小于目标值target
,将left
更新为mid + 1
,继续在右半部分查找。 - 如果
arr[mid]
大于目标值target
,将right
更新为mid - 1
,继续在左半部分查找。
- 计算中间位置
-
返回结果:
- 如果找到了目标元素,返回其索引。
- 如果循环结束后没有找到目标元素,返回
-1
。
总结
通过使用 int mid = left + (right - left) / 2;
,你可以有效避免由于 left
和 right
的和超出 int
范围导致的溢出问题,确保二分查找在所有情况下都能正确执行。
在数学上证明 left + (right - left) / 2
和 (left + right) / 2
得到的结果是相同的。两者之所以相等,归根结底在于它们的计算方式和中间步骤是相同的。
证明过程
令 ( L ) 表示 left
,( R ) 表示 right
。
-
表达式1:
(left + right) / 2
mid = L + R 2 \text{mid} = \frac{L + R}{2} mid=2L+R -
表达式2:
left + (right - left) / 2
mid = L + R − L 2 \text{mid} = L + \frac{R - L}{2} mid=L+2R−L
为了证明这两个表达式是等价的,我们可以将表达式2进行展开和简化:
L + R − L 2 = L + R 2 − L 2 = 2 L 2 + R 2 − L 2 = L + R 2 L + \frac{R - L}{2} = L + \frac{R}{2} - \frac{L}{2} = \frac{2L}{2} + \frac{R}{2} - \frac{L}{2} = \frac{L + R}{2} L+2R−L=L+2R−2L=22L+2R−2L=2L+R
由此可见,两个表达式是相等的。
原理
在数学上,两者的计算结果是一样的,因为加法和减法在整数范围内是可交换和结合的。然而在计算机科学中,特别是在考虑可能存在的整数溢出问题时,使用 left + (right - left) / 2
更为安全。
整数溢出问题
假设 left
和 right
都是非常大的整数,如果直接计算 (left + right) / 2
,有可能导致 left + right
超出整数范围,产生溢出。
比如,在 32 位系统中,最大整数值为 2147483647
。如果 left
和 right
的和超过这个值,就会发生溢出,从而导致计算结果错误。
通过 left + (right - left) / 2
这种方式,避免了直接相加可能带来的溢出问题,因为 right - left
的结果不会超过原来的范围。
实际代码示例
#include <iostream>
#include <limits.h>int main() {int left = INT_MAX - 1;int right = INT_MAX;// 计算两种方式的结果int mid1 = (left + right) / 2;int mid2 = left + (right - left) / 2;std::cout << "Using (left + right) / 2: " << mid1 << std::endl;std::cout << "Using left + (right - left) / 2: " << mid2 << std::endl;return 0;
}
结果验证
当 left
和 right
都接近 INT_MAX
时,(left + right) / 2
可能会导致溢出,而 left + (right - left) / 2
则可以避免这个问题,得到正确的结果。
通过这种方式,我们不仅证明了两者的数学等价性,还理解了在编程中为什么更推荐使用 left + (right - left) / 2
来避免潜在的整数溢出问题。
相关文章:
二分查找代码详解
二分查找代码实现 以下是完整的代码和解释: #include <stdio.h>int binarySearch(int arr[], int length, int target) {int left 0;int right length - 1;while (left < right) {int mid left (right - left) / 2; // 防止溢出if (arr[mid] target…...

uniapp的h5,读取本地txt带标签的文件
效果图 使用的回显的标签是u-parse,下面的网址讲了这个标签的相关 https://www.cnblogs.com/huihuihero/p/12978903.html 导入此插件 https://ext.dcloud.net.cn/plugin?id364 使用 uni.request({// 本地文件url: "/static/互联网医院医师端用户协议.txt…...

韦东山嵌入式linux系列-具体单板的按键驱动程序(查询方式)
1 GPIO 操作回顾 (1)使能模块; (2)设置引脚的模式(工作于GPIO模式); (3)设置GPIO本身(输入/输出); (4&…...

如何使用 API list 极狐GitLab 群组中的镜像仓库?
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab :https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署…...
PHP设计模式-简单工厂模式
核心: 一、定义一个接口类里面写规定好的方法。 interface Message{public function send(array $params);public function getMessage(array $params);public function getCode(array $params);} 二、定义产品类 、产品类继承接口类 class AlliYunSms implements …...

C语言航空售票系统
以下是系统部分页面 以下是部分源码,需要源码的私信 #include<stdio.h> #include<stdlib.h> #include<string.h> #define max_user 100 typedef struct ft {char name[50];//名字char start_place[50];//出发地char end_place[50];//目的地char …...
Oracle 19c打Datapatch数据补丁报错处理
Oracle 19c打Datapatch数据补丁报错处理 错误分析重新编译补丁验证安装完数据库补丁后,在数据补丁的步骤收到以下报错: Connecting to database...OK Gathering database info...done Bootstrapping registry and package to current versions...done Determining current s…...

Linux shell编程学习笔记66:ping命令 超详细的选项说明
0 前言 网络信息是电脑网络信息安全检查中的一块重要内容,Linux和基于Linux的操作系统,提供了很多的网络命令,今天我们研究最常用的ping命令。 1 ping命令 的功能、格式和选项说明 1.1 ping命令 的功能 简单来说, ping 命令 会…...

SSL/TLS和SSL VPN
1、SSL/TLS SSL安全套接字层:是一种加密协议,用于在网络通信中建立安全连接。它在应用层和传输层(TCP/IP)之间提供数据加密、服务器身份验证以及信息完整性验证 SSL只保护TCP流量,不保护UDP协议 TLS:传输层…...
浅谈WebSerice
一. 什么是WebService Web Service也称为web服务,它是一种跨编程语言和操作系统平台的远程调用技术。Web Service采用标准的SOAP协议传输(SOAP:Simple Object Access Protocol简单对象访问协议,soap属于w3c标准。并且soap协议是基…...
linux快速入门-学习笔记
linux快速入门-学习笔记 第一章:Linux系统概念及命令学习Linux系统基本概念命令终端介绍命令格式介绍Linux系统辨别目录与文件的方法通过文件详细属性辨别ls 查看目录/文件命令Linux 系统下的归属关系命令行编辑技巧Linux 基本权限的类别课后练习 第二章:…...
科普文:5种Linux下软件部署方式说明
在Linux世界里,高效、灵活地安装和管理软件是每个系统管理员和开发者的基本功。从传统的RPM包管理,到便捷的YUM软件仓库,再到颠覆性的Docker容器技术,Snap,源码安装,每一种方法都有其独到之处,适…...
Redisson中的RBlockingQueue的使用场景及例子
Redisson 的 RBlockingQueue 是一个实现了 Java BlockingQueue 接口的分布式队列,它可以用于在分布式系统中实现生产者-消费者模式。RBlockingQueue 提供了线程安全的阻塞队列操作,允许生产者在队列满时阻塞,消费者在队列空时阻塞,…...

【办公软件】Office 2019以上版本PPT 做平滑切换
Office2019以上版本可以在切页面时做平滑切换,做到一些简单的动画效果。如下在快捷菜单栏中的切换里选择平滑。 比如,在两页PPT中,使用同一个形状对象,修改了大小和颜色。 选择切换为平滑后,可以完成如下的动画显示。 …...
connect-multiparty中间件用法以及实例--文件上传中间件(保姆级别教学)
connect-multiparty中间件的用法包括安装和引入、基本设置、路由应用、文件处理以及安全和优化等步骤。 connect-multiparty是一个专为Connect和Express框架设计的文件上传中间件,它基于multiparty库,用于处理多部分表单数据,尤其针对文件上传…...

0503触发器的电路结构和工作原理
触发器的电路结构和工作原理 如何区分锁存器还是触发器, 看有没有这个三角符号,告诉是上升沿触发还是下降沿触发,没有三角符号就是电平触发。低电平触发就画个小圈。高电平触发就不画小圈。有小圈的三角就是下降沿触发 setup建立时间 hold 保…...
LeetCode:二叉树的中序遍历(C语言)
1、前序遍历:根左右 2、中序遍历:左根右 3、后序遍历:左右根 1、问题概述:二叉树中序遍历 2、示例 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2] 示例 2: 输入:root […...
MySQL数据库基本安装与部署
目录 概念 数据库的基本概念 关系型数据库 非关系型数据库 MySQL 商业版与社区版 示例 初始化MySQL 添加系统服务 概念 数据库的基本概念 数据(Data) 描述事物的符号记录包括数字、文字、图形、图像、声音、档案记录等以“记录”形式按统一的…...

paraFoam 运行 报错 usr/lib/x86_64-linux-gnu/libQt5Core.so 已解决
在日常项目开发中。使用ubuntu 视图开发的时候。报错 缺少 libQt5Core 核心组件! whereis libQt5Core.so.5sudo strip --remove-section.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 完美解决,并且能正常打开,前提是,…...

科技前沿:Llama 3.1的突破与革新
在科技的长河中,每一次模型的更新都是对人类智慧的致敬。今天,我们将聚焦于Meta公司最新发布的Llama 3.1系列模型,探索其在AI领域的前沿突破。 新模型的诞生 自去年以来,Meta公司不断推进人工智能技术的发展,终于在近…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...

论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...