【算法通关指南:算法基础篇】二分算法: 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

Qiuner赠书活动:算法图解、C++ Primer Plus、大话数据结构、Java项目全程开发实录、算法导论、深度学习、第一视角带你构建大模型GPT

Qiuner赠书活动:算法图解、C++ Primer Plus、大话数据结构、Java项目全程开发实录、算法导论、深度学习、第一视角带你构建大模型GPT

* 人年轻时常觉空虚,总想找点什么填满自己。买书,是我曾经的一种方式。但买得多,看得少。最近想着,这些书放着也是放着,不如抽几本送给粉丝,包邮寄出。 * 抽奖方式为点赞收藏评论:我要抽奖,即可。 💥 Qiuner ‖ Bug Free Life交流群火热招募中! ① 🎁 进群即送:ZEEKLOG评论防封脚本 + 真·活跃粉丝,助你快速提升文章热度! ② 📘 独家福利:免费赠送写作秘籍一份,教你玩转ZEEKLOG,揭秘大佬涨粉的秘密! ③ 🏆 大佬云集:热榜 Top10 的常客、数不清的万粉大佬都在群里,畅聊写作技巧、上榜经验、涨粉秘籍! ④ 💼 专属资源:合作推广、推文活动一应俱全,为你打开副业变现新途径! 👉 有兴趣的加文末联系方式,备注你的ZEEKLOG昵称,立刻拉你进群! 🔍 或直接搜索:Qiuner520,备注“写作”,即可入群交流~ 🧠 一起互帮互助,共同进步,让你的ZEEKLOG之路不再孤单! * 除了本文在评论区所赠书外,

By Ne0inhk
计算机基础知识总结(八股文总结----计算机网络、操作系统、数据库、c++、数据结构与算法)

计算机基础知识总结(八股文总结----计算机网络、操作系统、数据库、c++、数据结构与算法)

一、操作系统 0.内存管理 01.什么是虚拟内存?为什么需要虚拟内存? 虚拟内存为程序提供比实际物理内存更大的内存空间,同时提高内存管理的灵活性和系统的多任务处理能力。虚拟地址空间就是进程所能看到的内存空间,这段空间是连续的、独立的,实际地址空间则是内存上的空间,这段是所有进程共享的、有限的空间。虚拟内存就是把实际地址空间映射到虚拟地址空间的技术,这样就实现了内存隔离、内存扩展、物理内存管理、页面交换等技术。内存隔离就是每个进程都有自己的虚拟地址空间,因此一个进程无法访问另一个进程的内存。内存扩展就是虚拟内存让每个进程拥有比实际大的内存空间地址,可以处理更多的数据、更大的进程。物理内存管理,内存空间不足时把不常用的数据转移到硬盘上,释放内存,以助于更多进程使用。页面交换,进程可能会造成外部内存碎片,可能会导致内存空间不足,这时把不常用的数据交换到硬盘上,再交换回来,就能消除内存碎片,之前技术是内存分段,现在都是内存分页,一页或几页的内存交换就能解决内存不足的问题,而且效率高,内存分段的大数据在硬盘上读取速度慢。 02.什么是内存分段和分页?作用是什么? 内存分段是将一个程序

By Ne0inhk
【C/C++刷题集】string类(一)

【C/C++刷题集】string类(一)

🫧个人主页:小年糕是糕手 💫个人专栏:《C++》《Linux》《数据结构》《C语言》 🎨你不能左右天气,但你可以改变心情;你不能改变过去,但你可以决定未来! 目录 一、字符串最后一个单词的长度 二、验证回文串 三、字符串中的第一个唯一字符 四、反转字符串 一、字符串最后一个单词的长度 字符串最后一个单词的长度 这里我们看题目有一个注意点就是我们平常使用cin输入时遇到空格会停下来,在例子中我们可以看到他有A B C D,如果我们使用cin在遇到第一个A之后就会报错,所以这里我们要用到另一种输入方式:getline 他并不是一个成员函数,而是输入流的全局函数 getline(istream&, string&)(定义在 <string> 头文件中),作用是从输入流中读取一整行内容,存入 string 对象。 // 基础用法(读整行) getline(

By Ne0inhk
千面之法: 释放 C++ 多态的灵活威力

千面之法: 释放 C++ 多态的灵活威力

目录 1:多态的概念 1.1:概念 2.多态的定义与实现 2.1:多态的构成条件 2.2:虚函数 2.3:虚函数的重写 2.3.1:虚函数重写的两个例外 2.3.1.1:协变(基类与派生类函数的返回值不同,基类虚函数返回基类对象的指针或引用,派生类虚函数返回派生类对象的指针或引用时) 2.3.1.2:析构函数的重写 2.4:C++11 override和final 2.4.1:final关键字 2.4.2:override关键字 2.5:重载、

By Ne0inhk