当前位置: 首页 > news >正文

二分查找代码详解

二分查找代码实现

以下是完整的代码和解释:

#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; 是为了防止整数溢出。具体原因和解释如下:

原因

假设 leftright 都是非常大的正整数,那么 left + right 可能会超过 int 类型的表示范围,导致整数溢出。然而, left + (right - left) / 2 通过先计算 (right - left) / 2,确保了不会超过 int 的表示范围。

例子

假设 left = 2147483640right = 2147483646

  • left + right 的值是 4294967286,超过了 int 的最大值 2147483647,会导致溢出。
  • right - left 的值是 6,计算 (right - left) / 2 得到 3,然后 left + 3 的结果是 2147483643,没有溢出。

代码执行流程

  1. 初始化

    • left 初始化为数组的起始索引 0
    • right 初始化为数组的末尾索引 length - 1
  2. 二分查找循环

    • 计算中间位置 mid,使用 int mid = left + (right - left) / 2; 防止溢出。
    • 检查 arr[mid] 是否等于目标值 target。如果相等,返回 mid
    • 如果 arr[mid] 小于目标值 target,将 left 更新为 mid + 1,继续在右半部分查找。
    • 如果 arr[mid] 大于目标值 target,将 right 更新为 mid - 1,继续在左半部分查找。
  3. 返回结果

    • 如果找到了目标元素,返回其索引。
    • 如果循环结束后没有找到目标元素,返回 -1

总结

通过使用 int mid = left + (right - left) / 2;,你可以有效避免由于 leftright 的和超出 int 范围导致的溢出问题,确保二分查找在所有情况下都能正确执行。

在数学上证明 left + (right - left) / 2(left + right) / 2 得到的结果是相同的。两者之所以相等,归根结底在于它们的计算方式和中间步骤是相同的。

证明过程

令 ( L ) 表示 left,( R ) 表示 right

  1. 表达式1:(left + right) / 2
    mid = L + R 2 \text{mid} = \frac{L + R}{2} mid=2L+R

  2. 表达式2:left + (right - left) / 2
    mid = L + R − L 2 \text{mid} = L + \frac{R - L}{2} mid=L+2RL

为了证明这两个表达式是等价的,我们可以将表达式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+2RL=L+2R2L=22L+2R2L=2L+R

由此可见,两个表达式是相等的。

原理

在数学上,两者的计算结果是一样的,因为加法和减法在整数范围内是可交换和结合的。然而在计算机科学中,特别是在考虑可能存在的整数溢出问题时,使用 left + (right - left) / 2 更为安全。

整数溢出问题

假设 leftright 都是非常大的整数,如果直接计算 (left + right) / 2,有可能导致 left + right 超出整数范围,产生溢出。

比如,在 32 位系统中,最大整数值为 2147483647。如果 leftright 的和超过这个值,就会发生溢出,从而导致计算结果错误。

通过 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;
}

结果验证

leftright 都接近 INT_MAX 时,(left + right) / 2 可能会导致溢出,而 left + (right - left) / 2 则可以避免这个问题,得到正确的结果。

通过这种方式,我们不仅证明了两者的数学等价性,还理解了在编程中为什么更推荐使用 left + (right - left) / 2 来避免潜在的整数溢出问题。

相关文章:

二分查找代码详解

二分查找代码实现 以下是完整的代码和解释&#xff1a; #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&#xff0c;下面的网址讲了这个标签的相关 https://www.cnblogs.com/huihuihero/p/12978903.html 导入此插件 https://ext.dcloud.net.cn/plugin?id364 使用 uni.request({// 本地文件url: "/static/互联网医院医师端用户协议.txt…...

韦东山嵌入式linux系列-具体单板的按键驱动程序(查询方式)

1 GPIO 操作回顾 &#xff08;1&#xff09;使能模块&#xff1b; &#xff08;2&#xff09;设置引脚的模式&#xff08;工作于GPIO模式&#xff09;&#xff1b; &#xff08;3&#xff09;设置GPIO本身&#xff08;输入/输出&#xff09;&#xff1b; &#xff08;4&…...

如何使用 API list 极狐GitLab 群组中的镜像仓库?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…...

PHP设计模式-简单工厂模式

核心&#xff1a; 一、定义一个接口类里面写规定好的方法。 interface Message{public function send(array $params);public function getMessage(array $params);public function getCode(array $params);} 二、定义产品类 、产品类继承接口类 class AlliYunSms implements …...

C语言航空售票系统

以下是系统部分页面 以下是部分源码&#xff0c;需要源码的私信 #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 前言 网络信息是电脑网络信息安全检查中的一块重要内容&#xff0c;Linux和基于Linux的操作系统&#xff0c;提供了很多的网络命令&#xff0c;今天我们研究最常用的ping命令。 1 ping命令 的功能、格式和选项说明 1.1 ping命令 的功能 简单来说&#xff0c; ping 命令 会…...

SSL/TLS和SSL VPN

1、SSL/TLS SSL安全套接字层&#xff1a;是一种加密协议&#xff0c;用于在网络通信中建立安全连接。它在应用层和传输层&#xff08;TCP/IP&#xff09;之间提供数据加密、服务器身份验证以及信息完整性验证 SSL只保护TCP流量&#xff0c;不保护UDP协议 TLS&#xff1a;传输层…...

浅谈WebSerice

一. 什么是WebService Web Service也称为web服务&#xff0c;它是一种跨编程语言和操作系统平台的远程调用技术。Web Service采用标准的SOAP协议传输&#xff08;SOAP&#xff1a;Simple Object Access Protocol简单对象访问协议&#xff0c;soap属于w3c标准。并且soap协议是基…...

linux快速入门-学习笔记

linux快速入门-学习笔记 第一章&#xff1a;Linux系统概念及命令学习Linux系统基本概念命令终端介绍命令格式介绍Linux系统辨别目录与文件的方法通过文件详细属性辨别ls 查看目录/文件命令Linux 系统下的归属关系命令行编辑技巧Linux 基本权限的类别课后练习 第二章&#xff1a…...

科普文:5种Linux下软件部署方式说明

在Linux世界里&#xff0c;高效、灵活地安装和管理软件是每个系统管理员和开发者的基本功。从传统的RPM包管理&#xff0c;到便捷的YUM软件仓库&#xff0c;再到颠覆性的Docker容器技术&#xff0c;Snap&#xff0c;源码安装&#xff0c;每一种方法都有其独到之处&#xff0c;适…...

Redisson中的RBlockingQueue的使用场景及例子

Redisson 的 RBlockingQueue 是一个实现了 Java BlockingQueue 接口的分布式队列&#xff0c;它可以用于在分布式系统中实现生产者-消费者模式。RBlockingQueue 提供了线程安全的阻塞队列操作&#xff0c;允许生产者在队列满时阻塞&#xff0c;消费者在队列空时阻塞&#xff0c…...

【办公软件】Office 2019以上版本PPT 做平滑切换

Office2019以上版本可以在切页面时做平滑切换&#xff0c;做到一些简单的动画效果。如下在快捷菜单栏中的切换里选择平滑。 比如&#xff0c;在两页PPT中&#xff0c;使用同一个形状对象&#xff0c;修改了大小和颜色。 选择切换为平滑后&#xff0c;可以完成如下的动画显示。 …...

connect-multiparty中间件用法以及实例--文件上传中间件(保姆级别教学)

connect-multiparty中间件的用法包括安装和引入、基本设置、路由应用、文件处理以及安全和优化等步骤。 connect-multiparty是一个专为Connect和Express框架设计的文件上传中间件&#xff0c;它基于multiparty库&#xff0c;用于处理多部分表单数据&#xff0c;尤其针对文件上传…...

0503触发器的电路结构和工作原理

触发器的电路结构和工作原理 如何区分锁存器还是触发器&#xff0c; 看有没有这个三角符号&#xff0c;告诉是上升沿触发还是下降沿触发&#xff0c;没有三角符号就是电平触发。低电平触发就画个小圈。高电平触发就不画小圈。有小圈的三角就是下降沿触发 setup建立时间 hold 保…...

LeetCode:二叉树的中序遍历(C语言)

1、前序遍历&#xff1a;根左右 2、中序遍历&#xff1a;左根右 3、后序遍历&#xff1a;左右根 1、问题概述&#xff1a;二叉树中序遍历 2、示例 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root […...

MySQL数据库基本安装与部署

目录 概念 数据库的基本概念 关系型数据库 非关系型数据库 MySQL 商业版与社区版 示例 初始化MySQL 添加系统服务 概念 数据库的基本概念 数据&#xff08;Data&#xff09; 描述事物的符号记录包括数字、文字、图形、图像、声音、档案记录等以“记录”形式按统一的…...

paraFoam 运行 报错 usr/lib/x86_64-linux-gnu/libQt5Core.so 已解决

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

科技前沿:Llama 3.1的突破与革新

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

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...