【算法通关指南:算法基础篇】二分算法: 1.A-B 数对 2.烦恼的高考志愿

【算法通关指南:算法基础篇】二分算法: 1.A-B 数对 2.烦恼的高考志愿
在这里插入图片描述
🔥小龙报:个人主页
🎬作者简介:C++研发,嵌入式,机器人等方向学习者
❄️个人专栏:《C语言》《【初阶】数据结构与算法》
永远相信美好的事情即将发生
在这里插入图片描述

文章目录


前言

本文将通过两道经典二分查找例题 ——A-B 数对与烦恼的高考志愿,带你系统掌握二分查找的核心思想与实用技巧。从排序预处理到lower_bound、upper_bound的灵活运用,再到手动实现二分与边界细节处理,由浅入深讲解算法原理与代码实现,帮助你快速攻克二分查找题型,提升编程思维与解题效率

一、A-B 数对

1.1题目

链接:A-B 数对

在这里插入图片描述

1.2 算法原理

由于顺序不影响最终结果,所以可以先把整个数组排序,来研究是佛否有其他的性质。
由A − B = C 得:B = A − C,由于C是已知的数,我们可以从前往后枚举所有的A ,然后去前面找有多少个符合要求的B ,正好可以用二分快速查找出区间的长度。
【STL使用】
1.lower_bound:传入要查询区间的左右迭代器(注意是左闭右开的区间,如果是数组就是左右指针)以及要查询的值k,然后返回该数组中 >= k的第一个位置
2.upper_bound :传入要查询区间的左右迭代器(注意是左闭右开的区间,如果是数组就是左右指针)以及要查询的值k ,然后返回该数组中 > k 的第⼀个位置;

例:a = [10, 20, 20, 20, 30, 40] ,设下标从1 开始计数,在整个数组中查询20 :lower_bound(a + 1, a + 1 + 6, 20) ,返回a + 2 位置的指针;upper_bound(a + 1, a + 1 + 6, 20) ,返回a + 5 位置的指针;

然后两个指针相减,就是包含20 这个数区间的长度。

在这里插入图片描述

1.3代码

#include <iostream>#include <algorithm> using namespace std; typedef long long LL; const int N=2e5+10;LL a[N]; int main(){ int n, c; cin >> n >> c;for(int i =1; i <= n; i++) cin >> a[i];sort(a +1,a +1+ n);LL ret =0;for(int i =2; i <= n; i++){LL b = a[i]- c; ret +=upper_bound(a +1,a + i +1,b)-lower_bound(a +1, a +1+ i, b);} cout << ret << endl;return0;}
注:同时STL的使用范围很「局限」,查询「有序序列」的时候才有用,数组无序的时候就无法使用。但是我们的二分算法也能在「数组无序」的时候使用,只要有「二段性」即可

二、烦恼的高考志愿

2.1 题目

链接:烦恼的高考志愿

在这里插入图片描述

2.2 算法原理

先把学校的录取分数「排序」,然后针对每一个学生成绩 ,在「录取分数」中二分出≥ b的「第一个」位置pos,那么差值最小的结果要么在pos位置,要么在位置pos - 1,那么最后的不满意度求法就为:
abs(a[pos] − b)与abs(a[pos − 1] − b)的最小值。

注:细节问题
如果所有元素都大于b的时候,pos − 1 会在0 下标的位置,有可能结果出错;
• 如果所有元素都小于pos的时候,pos会在n的位置,此时结果倒不会出错,但是我们要想到这个细节问题,这道题不出错不代表下⼀道题不出错。
解决方法:加上两个左右护法,结果就不会出错了

2.3 代码

//烦恼的高考志愿 #include <iostream>#include <algorithm> using namespace std; typedef long long LL; const int N=1e5+10;LL a[N],b[N],m,n;LLfind(LL x){ int l =1, r = m;while(l < r){LL mid =(l + r)/2;if(a[mid]>= x) r = mid;else l = mid +1;}return l;} int main(){ cin >> m >> n;for(int i =1; i <= m; i++) cin >> a[i];//设置左护法 a[0]=-1e7;sort(a +1, a +1+ m);LL ret =0;for(int i =1; i <= n; i++){ cin >> b[i];LL pos =find(b[i]); ret +=min(abs(a[pos -1]- b[i]),abs(a[pos]- b[i]));} cout << ret << endl;return0;}

总结与每日励志

✨通过两道题目,我们学会了利用排序与二分查找快速统计数对、寻找最优匹配,理解了边界处理与 STL 函数的正确使用。二分的本质是寻找二段性,代码简洁却考验思维。愿你在算法学习路上保持耐心与专注,每一次思考都在沉淀成长,永远相信美好的事情即将发生,坚持下去,终会遇见更优秀的自己。

在这里插入图片描述

Read more

【C++指南】STL容器的安全革命:如何封装Vector杜绝越界访问与迭代器失效?

【C++指南】STL容器的安全革命:如何封装Vector杜绝越界访问与迭代器失效?

🌟 各位看官好,我是egoist2023! 🌍 种一棵树最好是十年前,其次是现在! 🚀 使用STL的三个境界:能用,明理,能扩展 👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦! 了解vector常用接口 vector是C++标准模板库中的部分内容,中文偶尔译作“容器”,但并不准确。它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。 常见构造 (constructor)构造函数声明接口说明vector()(重点)无参构造vector(size_type n, const value_type& val = value_type())构造并初始化n个valvector (const vector& x); (重点)拷贝构造vector (InputIterator first, InputIterator last)

By Ne0inhk
C++11新特性(下)----《Hello C++ Wrold!》(26)--(C/C++)

C++11新特性(下)----《Hello C++ Wrold!》(26)--(C/C++)

文章目录 * 前言 * lambda表达式 * 可变参数模板 * 展开参数包的方法 * 应用 * 包装器 * fiction包装器 * bind函数 * 作业部分 前言 在 C++11 标准带来的诸多革命性特性中,“简化代码编写” 与 “统一可调用对象管理” 是两大核心目标。lambda 表达式解决了传统仿函数 “定义繁琐、复用性低” 的痛点,让局部场景下的自定义逻辑(如排序规则、回调函数)能以更简洁的匿名函数形式实现;可变参数模板则打破了模板参数数量固定的限制,为 STL 容器(如emplace_back)和通用函数设计提供了灵活的参数处理能力;而 function 包装器与 bind 函数,则进一步整合了函数指针、仿函数、lambda 等不同类型的可调用对象,实现了统一管理与参数适配,甚至让可调用对象存储到容器中成为可能。 这些特性并非孤立存在 ——lambda 的底层依赖仿函数实现,可变参数模板为emplace系列接口提供了技术支撑,

By Ne0inhk
平衡二叉搜索树之 红黑 树的模拟实现【C++】

平衡二叉搜索树之 红黑 树的模拟实现【C++】

文章目录 * 红黑树的简单介绍 * 定义 * 红黑树的特性 * 红黑树的应用 * 全部的实现代码放在了文章末尾 * 准备工作 * 包含头文件 * 类的成员变量和红黑树节点的定义 * 构造函数和拷贝构造 * swap和赋值运算符重载 * 析构函数 * find * insert【重要】 * 第一步:按照二叉搜索树的方式插入新节点 * 第二步:调整颜色,维护红黑树的规则 * 情况一:新插入的节点的父亲节点颜色为黑 * 情况二:新插入的节点的父亲节点颜色为红,且叔叔节点不为空且为红 * 情况三:新插入的节点的父亲节点颜色为红,且叔叔节点为空或者为黑 * empty * size * 中序遍历 * 红黑树和AVL树的比较 * 全部代码 红黑树的简单介绍 定义 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,只能是Red或Black。 通过对任何一条从根到空节点的路径上各个结点着色方式的限制 红黑树确保没有一条路径会比其他路径长出俩倍,即最长路径的长度最多是最短

By Ne0inhk

C++:实现四舍五入(附带源码)

项目背景详细介绍 在数学计算、金融系统、工程测量、图像处理以及各种业务系统中,四舍五入是最基础、也是最容易被低估的一个问题。 很多初学者认为“四舍五入”只是简单地调用一个函数即可,例如: round(x) 但在实际开发中,问题远比想象复杂: * 不同业务对“四舍五入”的定义并不完全相同 * C++ 标准库中的 round / floor / ceil 行为容易混淆 * 浮点数本身存在精度误差 * 保留 N 位小数时,错误极易产生 例如: 2.675 四舍五入到 2 位小数 结果是 2.67 还是 2.68? 在不同语言、不同实现中,答案甚至可能不同。 因此,深入理解并亲自实现“四舍五入”逻辑,是 C+

By Ne0inhk