06-C++ 基本算法 - 二分法

news2024/10/7 2:20:48

在这里插入图片描述

📖 前言

在这个笔记中,我们将介绍二分法这种基本的算法思想,以及它在 C++ 中的应用。我们将从一个小游戏猜数字开始,通过这个案例来引出二分法的概念。然后我们将详细讲解什么是二分法以及它的套路和应用。最后,我们还会介绍 C++ STL 中的二分查找函数。让我们一起来探索吧!

🎯 什么是二分法

二分法是一种高效的搜索算法,通过将搜索范围不断缩小一半来快速找到目标值。它适用于有序数组或有序区间中查找特定元素的问题。二分法的基本思想是通过比较中间值与目标值的大小关系,来确定目标值可能存在的那一半区间,然后在该区间内继续查找。

🎮 小游戏猜数字

让我们通过一个小游戏来理解二分法的基本思想。假设有一个整数范围为 1 到 100,你需要猜一个隐藏的数字。每次猜测后,系统会告诉你猜的数字是大了还是小了,直到猜中为止。

在这里插入图片描述

这个小游戏的思路就是使用二分法来快速定位目标数字的范围。每次猜测时,将当前范围的中间数字与目标数字进行比较,根据比较结果来调整范围。通过不断缩小范围,最终可以找到目标数字。

🌟 二分法的套路

二分法有一些常见的套路和应用场景,我们将逐个介绍它们。

3.1 整数的二分

整数的二分是二分法的一种常见应用。我们以两个案例来说明整数的二分应用。

3.1.1 案例1: 力扣704. 二分查找

给定一个升序排列的整数数组 nums 和一个目标值 target,请你实现二分查找算法,如果目标值存在于数组中,则返回其索引,否则返回 -1。

示例代码:

#include <iostream>
#include <vector>
using namespace std;

int binarySearch(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

int main() {
    vector<int> nums = {1, 3, 5, 7, 9, 11};
    int target = 7;
    int result = binarySearch(nums, target);
    if (result != -1) {
        cout << "目标值 " << target << " 在数组中的索引为 " << result << endl;
    } else {
        cout << "目标值 " << target << " 不存在于数组中" << endl;
    }
    return 0;
}

运行结果:

目标值 7 在数组中的索引为 3

在上述代码中,我们使用二分法实现了查找目标值在有序数组中的索引。通过不断调整搜索范围的左右边界,并根据中间值与目标值的比较结果来确定下一步的搜索方向,最终可以找到目标值的索引。

3.1.2 案例2: 力扣350. 两个数组的交集 II

给定两个整数数组 nums1nums2,请你返回它们的交集。结果中每个元素的出现次数应与元素在两个数组中出现的次数一致(如果次数不一致,则取较小的次数)。结果不考虑顺序。

示例代码:

#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;

vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    unordered_map<int, int> counter;
    for (int num : nums1) {
        counter[num]++;
    }
    
    vector<int> result;
    for (int num : nums2) {
        if (counter[num] > 0) {
            result.push_back(num);
            counter[num]--;
        }
    }
    
    return result;
}

int main() {
    vector<int> nums1 = {1, 2, 2, 1};
    vector<int> nums2 = {2, 2};
    vector<int> result = intersect(nums1, nums2);
    
    cout << "两个数组的交集为:";
    for (int num : result) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}

运行结果:

两个数组的交集为:2 2

在上述代码中,我们使用哈希表记录了 nums1 中每个元素的出现次数,并通过遍历 nums2 找到与之对应的交集元素。通过减少交集元素的出现次数,最终可以得到交集的结果。

3.2 实数的二分

除了整数的二分,实数的二分也是二分法的一种应用。在实数的二分中,我们需要考虑精度问题,因为实数在计算机中无法表示为精确的值。下面是一个案例来说明实数的二分应用。

案例: 计算平方根

给定一个非负实数 x,要

求计算它的平方根并返回。我们可以使用二分法来逼近平方根的值,直到达到所需的精度。

示例代码:

#include <iostream>
using namespace std;

double sqrt(double x, double precision) {
    if (x < 0) {
        return -1; // 输入错误,返回 -1
    }
    
    double left = 0;
    double right = x;
    double mid;
    
    while (right - left > precision) {
        mid = left + (right - left) / 2;
        if (mid * mid <= x) {
            left = mid;
        } else {
            right = mid;
        }
    }
    
    return left;
}

int main() {
    double x = 16;
    double precision = 0.0001;
    double result = sqrt(x, precision);
    
    cout << "输入的数:" << x << endl;
    cout << "计算得到的平方根:" << result << endl;
    
    return 0;
}

运行结果:

输入的数:16
计算得到的平方根:4

在上述代码中,我们通过二分法逼近平方根的值,直到所达到的精度小于指定的 precision。通过不断调整搜索范围的左右边界,最终可以得到近似的平方根值。

💡 STL 二分查找

除了手动实现二分法算法,C++ STL(标准模板库)中也提供了二分查找的函数。这些函数包括 lower_bound()upper_bound(),它们可以方便地应用于有序容器中。

4.1 lower_bound()

lower_bound() 函数用于在有序容器中查找第一个大于或等于给定值的元素的迭代器。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> nums = {1, 3, 5, 7, 9};
    int target = 4;
    auto it = lower_bound(nums.begin(), nums.end(), target);
    
    if (it != nums.end()) {
        cout << "第一个大于或等于目标值的元素为:" << *it << endl;
    } else {
        cout << "没有找到满足条件的元素" << endl;
    }
    
    return 0;
}

运行结果:

第一个大于或等于目标值的元素为:5

在上述代码中,我们使用 lower_bound() 函数在有序容器 nums 中查找第一个大于或等于目标值 target 的元素。函数返回一个迭代器,指向满足条件的元素。

4.2 upper_bound()

upper_bound() 函数用于在有序容器中查找第一个大于给定值的元素的迭代器。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> nums = {1, 3, 5, 7, 9};
    int target = 4;
    auto it = upper_bound(nums.begin(), nums.end(), target);
    
    if (it != nums.end()) {
        cout << "第一个大于目标值的元素为:" << *it << endl;
    } else {
        cout << "没有找到满足条件的元素" << endl;
    }
    
    return 0;
}

运行结果:

第一个大于目标值的元素为:5

在上述代码中,我们使用 upper_bound() 函数在有序容器 nums 中查找第一个大于目标值 target 的元素。函数返回一个迭代器,指向满足条件的元素。

📚 总结

在本篇笔记中,我们学习了二分法这种基本的算法思想,并在 C++ 中通过案例和代码进行了详细讲解。我们了解了二分法的套路和应用场景,包括整数的二分和实数的二分。此外,我们还介绍了 C++ STL 中的二分查找函数 lower_bound()upper_bound(),它们可以方便地应用于有序容器中。希望通过本篇笔记的学习,你对二分法有了更深入的理解,并能够熟练应用于解决问题。祝你在算法学习的道路上越走越远!

本篇笔记内容主要参考了《算法竞赛进阶指南》和 LeetCode 等相关资源。

⭐️希望本篇文章对你有所帮助。

⭐️如果你有任何问题或疑惑,请随时向提问。

⭐️感谢阅读!

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

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

相关文章

基于VUE的音乐qq网站设计与实现(Java+spring boot+MySQL+VUE)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于VUE的音乐qq网站设计与实现&#xff08;Javaspring bootMySQLVUE&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java springboot框架 my…

基于RASC的keil电子时钟制作(瑞萨RA)(2)----配置keil以及使用串口进行打印

基于RASC的keil电子时钟制作_配置keil以及使用串口进行打印 概述参考文档硬件准备视频教程新建工程保存工程路径芯片配置工程模板选择时钟设置管脚配置UART配置UART属性配置DEBUG配置printf()函数设置e2studio堆栈生成工程设置RA Smart Configurator到Keilkeil配置Ddbug设置R_S…

SpringSecurity(6.1.x版本) 认证,授权,自定义登录,内部机制探讨

SpringSecurity 文章目录 SpringSecurityCSRF跨站请求伪造攻击SFA会话固定攻击XSS跨站脚本攻击开发环境搭建认证直接认证使用数据库认证自定义验证 其他配置自定义登录界面记住我功能 授权基于角色授权基于权限授权使用注解权限判断 内部机制探究授权校验流程安全上下文安全上下…

嵌入式必学~黑马新教程发布,你准备好了吗

科技的不断发展&#xff0c;给计算机行业带来了很多机会&#xff0c;嵌入式开发的前景也越来越广阔&#xff0c;过去的嵌入式是&#xff1a;电器、机械、交通设备。现在的嵌入式是&#xff1a;手机、智能家居、物联网、新能源、新基建、芯片...... 随着国家政策的倾斜&#xf…

配置uprof环境

AMD uprof 1/从AMD μProf | AMD处下载两个文档 2/解压 tar jxvf filename 3/将.rpm转换成deb Ubuntu的软件包格式是deb&#xff0c;如果要安装rpm的包&#xff0c;则要先用alien把rpm转换成deb。 sudo apt-get install alien #alien默认没有安装&#xff0c;所以首先要安…

2023-07-10 linux IIO子系统使用学习,在TI 的ads1015驱动里面看到相关使用,故花点时间进行简单的学习,入门级别,纪录点滴。

一、Linux IIO&#xff08;Industrial I/O&#xff09;架构是Linux内核提供的一种用于支持各种类型传感器和数据采集设备的子系统&#xff0c;包括温度、压力、湿度、加速度、光度等多种传感器。 二、这个就是ads1015的驱动&#xff0c;里面用到iio子系统。 ti-ads1015.c adc…

数据脱敏的 3 种常见方案,好用到爆!

1.SQL数据脱敏实现 MYSQL(电话号码,身份证)数据脱敏的实现 -- CONCAT()、LEFT()和RIGHT()字符串函数组合使用&#xff0c;请看下面具体实现-- CONCAT(str1,str2,…)&#xff1a;返回结果为连接参数产生的字符串 -- LEFT(str,len)&#xff1a;返回从字符串str 开始的len 最左字…

力扣 -- 123. 买卖股票的最佳时机 III

题目链接&#xff1a;123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 参考代码&#xff1a; class Solution { public:int maxProfit(vect…

OKCC呼叫中心的坐席监控功能有什么

最近很多客户都在跟我谈他们企业的电话客服工作量都非常大&#xff0c;虽然客服人员在服务时应该态度谦和&#xff0c;但是遇到难缠的客户&#xff0c;客服人员总有脾气忍不住的时候&#xff0c;言语上会带有情绪&#xff0c;这些客服人员会因为服务水平欠佳让客户不满意从而产…

【Python】json 格式转换 ( json 模块使用 | 列表转 json | json 转列表 | 字典转 json | json 转字典 )

文章目录 一、json 格式转换1、json 模块使用2、代码示例分析 - 列表转 json3、代码示例分析 - 字典转 json json 格式 字符串 与 Python 中的 字典 dict 和 列表 list 变量 可以无缝转换 ; 调用 json.dumps 函数 可以将 Python 列表 / 字典 转为 json ;调用 json.loads 函数 …

基于Vue + 数据组装 + axios请求接口 实现图书信息提交功能实战

前言 上节回顾 上一节针对图书信息录入前的准备做了讲解&#xff0c;主要是使用ElementUI的el-form做录入界面基本布局&#xff0c;包含了el-input el-select el-date-picker 还有图片上传等组件。同时在布局完成后&#xff0c;配合使用el-form自带的rules进行数据提交前验证…

生鲜小程序怎么做

生鲜超市小程序功能介绍 1、产品展示&#xff1a;果蔬生鲜的图片展示&#xff0c;食欲满满的食材图&#xff0c;丰富的生鲜品类&#xff0c;细致的产品描述&#xff0c;提高用户的购买欲望和复购率。 2、在线支付&#xff1a;用户选择好所需食材在线下单&#xff0c;利用第三…

[Linux] 守护进程介绍、服务器的部署、日志文件...

守护进程 我们使用的系统中, 一般以服务器的方式工作 对外提供服务的服务器, 都是以守护进程的方式在系统中工作的. 比如, 我们使用Linux服务器时, 大多都会使用一些终端软件通过ssh远程连接服务器使用. 这就是因为, Linux服务器中 通常默认运行着 ssh服务器的守护进程: 守护…

利用数据分析告警机制,实现鸿鹄与飞书双向集成

需求描述 实现鸿鹄与飞书的双向集成&#xff0c;依赖鸿鹄的告警机制&#xff0c;可以发送用户关心的信息到飞书。同时依赖飞书强大的卡片消息功能&#xff0c;在飞书消息里面能够通过链接&#xff08;如下图&#xff09;返回到鸿鹄以方便用户进一步排查和分析问题。 解决方案 1…

Goby 漏洞发布|致远 M1 移动端 userTokenService 代码执行漏洞

漏洞名称&#xff1a;致远 M1 移动端 userTokenService 代码执行漏洞 English Name&#xff1a;seeyon M1 Server userTokenService Code Execution Vulnerability CVSS core: 10.0 影响资产数&#xff1a;7050 漏洞描述&#xff1a; 致远 M1 Server是一个移动服务。致远 …

7zip修复右击菜单的问题

以管理员权限运行7-Zip File Manager后 &#xff0c;要在右键菜单显示 图标&#xff0c;不然就有问题

苍穹外卖day03——菜品管理业务代码开发

目录 公共字段自动填充——问题分析和实现思路 公共字段自动填充——代码实现(1) 公共字段自动填充——代码实现完善(2) 新增菜品——需求分析与设计 产品原型 ​编辑 接口设计 ​编辑 数据库设计 新增菜品——代码开发1(文件上传接口) 配置文件 Controller层代码 前后…

项目名称:智能家居边缘网关项目

一&#xff0c;项目介绍 软件环境: C语言 硬件环境: STM32G030C8TX单片机开发板 开发工具: Linux平台GCC交叉编译环境以及ukeil (1)边缘网关概念 边缘网关是部署在网络边缘侧的网关&#xff0c;通过网络联接、协议转换等功能联接物理和数字世界&#xff0c;提供轻量化的联接管…

大语言模型的预训练[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相关理论知识和模型实现、模型应用以及各个版本之间的区别详解

大语言模型的预训练[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相关理论知识和模型实现、模型应用以及各个版本之间的区别详解 1.GPT 模型 1.1 GPT 模型简介 在自然语言处理问题中&#xff0c;可从互联网上下载大量无标注数据&#xff0c;而针对具体问题的有标注数据却非常少&#x…

原型设计用什么比较好?这4款值得体验

无论是UI还是UX设计师&#xff0c;工作中肯定少不了交互设计。在设计原型图时&#xff0c;一款好用的原型设计工具肯定是必不可少&#xff0c;本文就整理了4款为大家推荐&#xff0c;一起来看看吧 即时设计 即时设计是一款更适合国内UI或UX设计师和产品经理使用的原型设计工具…