C++算法学习2:二分算法精讲

news/2025/3/17 21:57:45/

一、实数二分法回顾

1.1问题背景

在1~2的范围内找到一个x,使得式子5x2 -9x +1 的绝对值<10-9(即无限接近0) 要求:x精确到小数点后9位。

换句话说也就是求:就是求方程  5x2- 9x + 1 =0 在1~2内的近似解

1.2怎么找到这个x呢?

我们需要一个一个试,关键是:试哪些数?

先试边界1和2

将1、2分别带入下列方程

令y = 5x2 - 9x + 1 ,目标:|y| <10-9

得到y=-3、y=3

下一个试谁呢?

将x=1.5带入y = 5x2 - 9x + 1

1.3接下来我们往左边试还是往右边试?

应该往右试:

我们接下来要做的就是反复的左右试题x的值,直到y的绝对值小于10的-9次方为止。

1.4 算法实现

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;int main() {double left = 1, right = 2;double x = (left + right) / 2;double y = 5 * x * x - 9 * x + 1;while (abs(y) > 1e-9) {if (y > 0) right = x;  // 解在左侧else left = x;         // 解在右侧x = (left + right) / 2;y = 5 * x * x - 9 * x + 1;}cout << fixed << setprecision(9) << x;return 0;
}

核心特点

  • 终止条件:解的精度达到 1e-9

  • 区间更新:直接赋值 left = x 或 right = x

  • 中间值计算:无需考虑整数溢出问题


二、整数二分法解析

猜数字游戏

输入一个范围在 [1, 1000] 内的数字,让计算机去猜,看使用二分法,计算机需要几次就能猜出来:

#include<iostream>
using namespace std;
int main(){int sum=0;//记录一共猜了几次数 int b=0,e=1000,x=173;//b,e左边界和右边界确定了数据范围,x=173是我们猜的数字 //使用二分法开始猜数 while(b<=e){//左边界小于等于右边界是整数二分的条件 int mid=(b+e)/2;//获取中间值 if(x==mid){cout<<"猜对了"<<endl;break;}else if(mid>x){cout<<"大了"<<mid<<endl; e=mid-1;//更新右边界值 sum++;}else{cout<<"小了"<<mid<<endl; b=mid+1;//更新左边界值 sum++;}}cout<<"一共猜了几次"<<sum;        return 0;
} 

与实数二分的核心差异

特性实数二分整数二分
终止条件精度达到阈值left > right
中间值计算直接取平均需要处理整数除法特性
区间更新直接赋值需要±1操作
内存消耗浮点运算整型运算

三、整数二分经典应用

练习:在数组中查找数字3的位置

问题要求

  1. 输入无序数组

  2. 输出首次出现3的位置(从1开始计数)

  3. 不存在时输出-1

实现方案

#include <iostream>
#include <algorithm>
using namespace std;struct Item {int id;int value;
} a[100];bool cmp(Item a, Item b) {return a.value < b.value;
}int main() {int n;cin >> n;for (int i = 1; i <= n; ++i) {a[i].id = i;cin >> a[i].value;}// 排序保持原始位置sort(a + 1, a + n + 1, cmp);// 二分查找int left = 1, right = n, res = -1;while (left <= right) {int mid = left + (right - left) / 2;if (a[mid].value >= 3) {if (a[mid].value == 3) res = a[mid].id;right = mid - 1;} else {left = mid + 1;}}// 验证是否为首次出现if (res != -1) {for (int i = right + 1; i <= left; ++i) {if (a[i].value == 3) {res = min(res, a[i].id);}}}cout << (res != -1 ? res : -1);return 0;
}

关键点解析

  1. 结构体排序:保存原始位置信息

  2. 查找策略

    • 查找第一个≥3的元素

    • 反向扫描确认首次出现位置

  3. 边界处理:处理多个相同值的情况


四、c++标准库二分函数解析

1. lower_bound 函数

功能描述

有序区间中查找第一个大于或等于目标值的元素位置

使用模板
// 函数原型
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val);// 示例代码
int a[] = {4,6,1,7,9,6,5,12,15,8}; 
sort(a, a+10); // {1,4,5,6,6,7,8,9,12,15}int target = 11;
auto it = lower_bound(a, a+10, target); 
int pos = it - a;  // 计算索引位置if(pos < 10) {cout << "找到的数是:" << *it << " 位置是:" << pos;  // 输出:12 位置8
} else {cout << "未找到";
}
特性说明
  • 时间复杂度:O(log n)

  • 前提条件:区间必须已排序

  • 返回值:若找到返回对应迭代器,否则返回last

2. upper_bound 函数

功能描述

有序区间中查找第一个严格大于目标值的元素位置

使用对比
int a[] = {1,2,2,3,3,3,4,5};
int n = sizeof(a)/sizeof(int);int val = 3;
auto lb = lower_bound(a, a+n, val); // 指向第一个3(索引3)
auto ub = upper_bound(a, a+n, val); // 指向第一个4(索引6)cout << "元素3的个数:" << ub - lb;  // 输出3

3. 函数对比表

特性lower_boundupper_bound
查找条件≥ target> target
返回值位置第一个可插入位置(保序)最后可插入位置(保序)
常见用途查找元素是否存在统计元素出现次数
未找到返回值指向第一个>target的元素指向最后一个元素的下一个位置

五、综合应用实例

案例:求解三次方程近似根

double cube_root(double L, double R) {const double eps = 1e-12;while (R - L > eps) {double mid = (L + R) / 2;if (mid*mid*mid > 27) {  // 求³√27的近似值R = mid;} else {L = mid;}}return L;
}// 输出:3.000000000000

五、二分算法适用场景

  1. 有序数据集:单调递增/递减序列

  2. 离散数值查找:整数集合中的定位

  3. 分治问题:最大值最小化/最小值最大化问题

  4. 高效查询:时间复杂度O(log n)


六、常见错误及规避

  1. 死循环问题

    • 确保区间更新有进展

    • 使用标准模板:left = mid + 1 / right = mid - 1

  2. 整数溢出

    int mid = left + (right - left) / 2;  // 正确写法
  3. 边界处理

    • 初始化时明确开闭区间

    • 终止条件验证 left <= right


通过系统掌握实数与整数二分法的实现差异,结合经典应用场景的实战训练,可显著提升算法设计能力与代码实现水平。


http://www.ppmy.cn/news/1579920.html

相关文章

python爬虫笔记(一)

文章目录 html基础标签和下划线无序列表和有序列表表格加边框 html的属性a标签&#xff08;网站&#xff09;target属性换行线和水平分割线 图片设置宽高width&#xff0c;height html区块——块元素与行内元素块元素与行内元素块元素举例行内元素举例 表单from标签type属性pla…

【STM32】USART串口协议串口外设-学习笔记

串口协议 通信接口 通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统。比如STM32芯片内部集成了很多功能模块&#xff0c;像定时器计数、PWM输出、AD采集等等。这些都是芯片内部的电路&#xff0c;这些电路的配置寄存器&#xff0c;数据寄存…

【DeepSeek应用】DeepSeek模型本地化部署方案及Python实现

DeepSeek实在是太火了,虽然经过扩容和调整,但反应依旧不稳定,甚至小圆圈转半天最后却提示“服务器繁忙,请稍后再试。” 故此,本文通过讲解在本地部署 DeepSeek并配合python代码实现,让你零成本搭建自己的AI助理,无惧任务提交失败的压力。 一、环境准备 1. 安装依赖库 …

RustDesk自建远程桌面服务教程

原文&#xff1a;https://www.dong-blog.fun/post/1676 有几家非要收钱&#xff0c;不收钱就慢得要死&#xff0c;自建一个自己用肯定就快了。 买服务器 首先去这里买一台服务器&#xff1a;https://acck.io/shop/ 五块钱一台。 然后去服务器装docker compose&#xff1a;h…

Redis集群模式(Cluster)深度解析:架构设计与数据分片实战

引言 随着业务规模的扩张&#xff0c;单机Redis实例面临内存、吞吐量和可用性三大瓶颈。​Redis Cluster作为官方分布式解决方案&#xff0c;通过数据分片&#xff08;Sharding&#xff09;、主从复制和故障自动转移&#xff0c;实现了高性能、高可用、线性扩展的分布式缓存架…

微博发布Q4及全年财报:微博成汽车手机新品营销主阵地

3月13日&#xff0c;微博发布2024年第四季度及全年财报。四季度微博总营收4.568亿美元&#xff0c;约合33.05亿元人民币&#xff0c;四季度调整后运营利润达到1.362亿美元&#xff0c;约合9.95亿元人民币&#xff0c;超华尔街预期&#xff1b;2024年全年&#xff0c;微博总营收…

超精密工件小孔几何尺寸测量:自动化解决方案

下载链接&#xff1a;&#xff08;最新版本&#xff09;超精密工件小孔几何尺寸测量&#xff1a;自动化解决方案python脚本代码&#xff0c;可直接运行&#xff0c;内包含测试数据&#xff0c;亲测好用资源-CSDN文库 在现代制造业中&#xff0c;超精密工件的质量控制至关重要&a…

Oracle 查询数据库对象的DDL语句

可使用 DBMS_METADATA.GET_DDL()函数 查询数据库对象的DDL语句。 DBMS_METADATA.GET_DDL()函数 语法结构&#xff1a; SELECT DBMS_METADATA.GET_DDL(OBJECT_TYPE, NAME, SCHEMA) FROM DUAL;参数说明&#xff1a; OBJECT_TYPE&#xff1a;对象的类型,如TABLE、INDEX、FUNTION…