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

在这里插入图片描述

📖 前言

在这个笔记中,我们将介绍二分法这种基本的算法思想,以及它在 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.mzph.cn/news/2808.shtml

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

相关文章

在 3ds Max 中创建逼真的玻璃材质

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 尽管本教程基于 3ds Max&#xff0c;但相同的设置适用于许多其他 3D 产品。 注意&#xff1a;单击每个步骤中的缩略图可查看更大的屏幕截图&#xff0c;其中包括视口和用户界面的相关部分。 步骤 1由于本教…

广西学子复读15年,不服从分配。网友:完全是浪费时间

广西学子复读15年&#xff0c;不服从分配。网友&#xff1a;完全是浪费时间 唐尚珺的复读行为引起了网友们的不同解读。有人认为他是一个执念深重的人&#xff0c;目标是考上清华北大&#xff0c;但这个说法是否真实&#xff0c;我们无法确定。无论如何&#xff0c;我们必须认识…

electron+vue3全家桶+vite项目搭建【24】设置应用图标,打包文件的图标

文章目录 引入实现步骤测试结果 引入 demo项目地址 在electron中&#xff0c;我们可以通过electron-builder的配置文件来设置打包后的应用图标 实现步骤 因为mac环境下的图标需要特殊格式&#xff0c;这里我们可以利用electron-icon-builder进行配置 1.引入相关依赖 # 安…

GPT 如此强大,我们可以利用它实现什么?

GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种基于Transformer结构的预训练语言生成模型&#xff0c;由OpenAI研发。它可以生成高质量的自然语言文本&#xff0c;取得了很好的效果&#xff0c;被广泛应用于各个领域。以下是一些利用GPT实现的应用。 一…

ts中setState的类型

两种方法: 例子: 父组件 const [value, setValue] useState(); <ChildsetValue{setValue} />子组件 interface Ipros {setValue: (value: string) > void } const Child: React.FC<Ipros> (props) > {}

SpringMvc配置静态资源访问路径

文章目录 1. 整体流程2. registry.addResourceHandler()2.1 函数分析2.2 结果演示 3. ResourceHandlerRegistration.addResourceLocations()3.1 函数分析3.2 结果演示 1. 整体流程 1. 写一个配置类继承WebMvcConfigurationSupport 2. 利用 registry.addResourceHandler("…

Vue成绩案例实现添加、删除、显示无数据、添加日期、总分均分以及数据本地化等功能

一、成绩案例 ✅✅✅通过本次案例实现添加、删除、显示无数据、添加日期、总分均分以及数据本地化等功能。 准备成绩案例模板&#xff0c;我们需要在这些模板上面进行功能操作。 <template><div class"score-case"><div class"table">…

nginx基础3——配置文件详解(实用功能篇)

文章目录 一、平滑升级二、修饰符2.1 无修饰符效果2.2 精准匹配&#xff08;&#xff09;2.3 区分大小写匹配&#xff08;~&#xff09;2.4 不区分大小写匹配&#xff08;~*&#xff09;2.5 匹配优先级 三、访问控制四、用户认证五、配置https六、开启状态界面七、rewrite重写u…

matplotlib 3D

import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np# 创建一个三维坐标轴 fig plt.figure() ax fig.add_subplot(221, projection3d) xx fig.add_subplot(222) yy fig.add_subplot(223) xy fig.add_subplot(224)# 生成示例数据…

关于你欠缺的NoSQL中的redis和mongoDB

文章目录 前言一、在string list hash结构中&#xff0c;每个至少完成5个命令&#xff0c;包含插入 修改 删除 查询&#xff0c;list 和hash还需要增加遍历的操作命令1、STRING类型2、List类型数据的命令操作&#xff1a;3、举例说明list和hash的应用场景&#xff0c;每个至少一…

echarts图例对齐

富文本不生效&#xff0c;是没有设置lineHeight

企业内部FAQ系统的搭建重要性是什么?

企业内部FAQ系统&#xff08;Frequently Asked Questions&#xff0c;常见问题解答系统&#xff09;的搭建对于企业来说具有重要的意义。它可以帮助企业有效地管理和解决员工和客户的常见问题&#xff0c;提高工作效率和服务质量。 企业内部FAQ系统搭建的重要性&#xff1a; …

Python批量实现Word、EXCLE、PPT转PDF文件

一、绪论背景 在日常办公和文档处理中&#xff0c;有时我们需要将多个Word文档、Excel表格或PPT演示文稿转换为PDF文件。将文档转换为PDF格式的好处是它可以保留文档的布局和格式&#xff0c;并且可以在不同平台上进行方便的查看和共享。 本篇博文将介绍如何使用Python编程语言…

lua脚本语言学习笔记

Lua 是一种轻量小巧的脚本语言&#xff0c;用标准C语言编写并以源代码形式开放&#xff0c; 其设计目的是为了嵌入应用程序中&#xff0c;从而为应用程序提供灵活的扩展和定制功能。 因为我们使用redis的时候一般要写lua脚本&#xff0c;这篇文章就介绍一下lua脚本语言的基础用…

旅行社优惠卡app软件开发

旅游行业的不断发展&#xff0c;越来越多的旅行社开始推出各种优惠卡来吸引游客。而随着智能手机的普及&#xff0c;开发一款旅行社优惠卡APP软件成为了一种必然的趋势。 该软件的主要功能是提供旅行社的各种优惠卡信息&#xff0c;包括优惠卡的种类、价格、使用范围、有效…

Pytorch如何打印与Keras的model.summary()类似的输出

1 Keras的model.summary() 2 Pytorch实现 2.1 安装torchsummary包 pip install torchsummary2.2 代码 import torch import torch.nn as nn import torch.nn.functional as F from torchsummary import summaryclass Net(nn.Module):def __init__(self):super(Net, self).__…

【Spring Boot学习一】创建项目 Spring Boot的配置文件

目录 一、安装插件 二、创建Spring Boot项目 1、创建项目 1.1 使用IDEA创建 1.2 网页版本创建 2、项目目录介绍与运行 三、Sping Boot的配置文件&#xff08;重点&#xff09; &#x1f337;1、.properties配置文件 &#xff08;1&#xff09;基础语法&#xff1a;Key …

我在VScode学Java类与对象(Java显式参数和隐式参数、静态方法+main方法、Java访问修饰符、static关键字、Java的包、对象数组)第三辑

我的个人博客主页&#xff1a;如果’真能转义1️⃣说1️⃣的博客主页 关于Java基本语法学习---->可以参考我的这篇博客&#xff1a;《我在VScode学Java》 续《我在VScode学Java&#xff08;Java的类与对象&#xff09;》 方法会操作对象并访问他们的实例字段。 伍._. 显式参…

elementUI el-radio 无法点击的问题

<el-form-item label"B端客户类型" prop"user_type"><template slot"label"><span>B端客户类型</span><el-tooltip effect"dark" placement"top" content"B端大客户账期有效,只有设置该类型…

javascript实现久久乘法口诀表、document、write、console、log

文章目录 正序乘法口诀表倒序乘法口诀表logconsoledocumentwrite 正序乘法口诀表 function multiplicationTable() {for (let i 1; i < 9; i) {let val ;for (let j 1; j < i; j) {document.write(j * i (i * j) &nbsp );val ${j}*${i}${i * j} ;}consol…