分治算法(1)——二分查找、STL函数库的应用第五弹——二分函数
2021-02-07 11:16
标签:二分法 sea 答案 tle ret stl main info false 我们在做题的时候,经常会遇到一些需要分治的问题。(这是真的 今天的主角是——二分查找(开头提到过)。 二分查找,是针对于有序排列的数据调用而生的一种数据调用方法。 听上去很高端?我来讲个故事,大家肯定一下就会明白。 记得坐车的时候会收听电台,主持人有时会和观众玩这样一个游戏: 主持人在纸卡上写一个0-100的数字,要求听众在30秒内猜出这个数。 当听众说出一个数的时候,主持人会说出这个数相对于纸卡上的数是大了还是小了。 当然了,我相信主持人其实根本就没往纸卡上写数。 他也不会那么容易的让听众拿到奖品,所以每次猜一个数,他总会让听众尽可能少的排除错误答案。 比如你猜75,他会说“比75小”,这样你就只排除了25个错误答案。 那么怎么猜才是最聪明、最稳健的呢? 相信很多同学都已经想到了:猜50。这样就算主持人想阻挠拿到奖品,也可以一下子排除掉一半的错误答案。 那么猜完50呢?假如主持人说“比50大”,我们又该猜几呢? 对了——75,这样又能从剩下的里面排除一半错误答案。 ——没错,这样每次缩小一半结果范围,不断缩小答案可能存在的区间,最终找到答案的方法,就叫做“二分法”。 如果我们使用二分法,在100个数中查找一个数,最坏的情况也只需要7次运算,而如果暴力枚举的话,可能就要几十次。 所以复杂度O(logn),而暴力的复杂度却是O(n)。 当然,使用二分法也有条件——数列必须有序,按照从小到大排序或者从大到小排序才可以。 (这里最好从小到大,笔者后面的代码也是按照从小到大来二分的) 有一些加(丧)强(心)数(病)据(狂)的题目是这样的: 对于一个长度为n的不降序列,给出m组数据,请找出每个数在此序列中第一次出现的位置。 对于100%的数据,数据个数 n
如果暴力枚举的话,可爱的评测姬会非常不屑地回复你TLE三个字。(但是可以拿到部分分,唔,大概20~30分吧,不会太多的) 为了AC,我们就要用到二分,因为二分法的时间复杂度要优秀的多。 我们既然已经知道二分的原理了,剩下的就是怎么模拟二分了。 (鲁迅说过,算法来自生活实际,是模拟出来的。比如高精度算法,是模拟竖式……) 思路如下。 对于一个非常大的不降序列,注意必须是不降!!!我们有如下操作: 1、按照开头故事里的思路,我们要做出两个指针,分别指向这个序列的开头和末尾,表示二分到现在,答案是在这两个指针所指区间之内。 2、找出中间元素的值,然后比较它和所查找的那个数的值。如果比他大,那么排除比中间值小的数,把开头的指针(称为左指针)移动到中间值的位置;如果比他小,那么排除比中间值大的数,把末尾的指针(称为右指针)移动到中间值的位置。 3、重复步骤(2),直到找到该元素,返回元素下标。需要注意的是:如果左指针比右指针还要靠右(指向元素下标比右指针大),说明这个元素在此序列里不存在,这时,我们要退出循环二分查找。 具体代码如下,我已经竭尽一个蒟蒻所能的做了注释: 这里还有一个要点,就是我这么写二分,只能对升序序列生效,如果序列中有多个相同的值,这个函数返回哪一个的下标我就不知道了。 如果题目中有要求,返回第一次出现的下标,我们需要手动在函数里加一个循环,找到该元素第一次出现的位置。 如果需要查找最接近某元素的值,二分到最后,确定该元素不在序列中,我们可以比较左指针所指元素的前一个或者后一个元素和左指针所指的元素,看看哪一个更接近即可。 这些只需要对函数做一些小小的修改,都很好写,笔者就不多BB了。 终于到了STL函数库出场的时间了! 伟大的#include! 为了方便我们这些蒟蒻编程和dalao们压缩代码,减少工作量,神犇们创造了这三个函数: lower_bound()、upper_bound()、binary_search() 我们来一位一位介绍。 首先,binary_search()函数,作用:对一个不降序列进行二分查找,如果所查找的值在序列中出现了,返回true,没有出现,返回false。 然后,lower_bound()函数,作用:对一个不降序列进行二分查找,返回第一个大于等于所查找的值的元素下标,注意返回的是指针变量!!! 最后,upper_bound()函数,作用:对一个不降序列进行二分查找,返回第一个大于所查找的值的元素下标,注意返回的是指针变量!!! 这么方便的函数怎么用? 我们设置以下变量: num[ ](需要被查找的序列); lenth(序列长度); x(需要查找的元素); 那么这几个函数使用的格式大概是这样的: binary_search(num,num+lenth,x); lower_bound(num,num+lenth,x); upper_bound(num,num+lenth,x); 放到具体代码里是这样的: 需要注意的是,因为这lower_bound()和upper_bound()这两个函数返回的值是指针变量,所以要把它变成int类型,要减去数组名。 ps:如果你所查找的数值比序列里最大的那个数还要大,lower_bound()和upper_bound()这两个函数返回的下标是lenth+1,注意这个东西有可能是越界的,所以不想RE的话就稍微处理一下吧!!! 由于笔者今天刚刚粗略的学了学STL大法,还不是很熟练,所以做题不多(只有一道)望谅解,有时间的话会专门发一篇二分查找的题解。 这个题,因为给出的序列已经是非降序列了,所以不需要先sort()来排序。 思路很简单——lower_bound()查找,需要注意的是比较的时候,不要越界。 先上加注释的代码,相信大家一看就懂。、 好了,今天的学习分享就到这里了,最后BB一句,能用STL的,我们绝对不要手写二分,不仅容易写错,而且费时间(蒟蒻思维) 记住这三个函数!!!lower_bound()、upper_bound()、binary_search(),非常方便,非常方便,非常方便!!! 老规矩——祝大家,身(少)体(掉)健(头)康(发)。 分治算法(1)——二分查找、STL函数库的应用第五弹——二分函数 标签:二分法 sea 答案 tle ret stl main info false 原文地址:https://www.cnblogs.com/zaza-zt/p/12776296.html分治算法(1):二分查找!昨天刚说不写算法了,但是突然想起来没写过分治算法的博客,所以强迫症的我……
STL函数库第五弹——二分函数lower_bound()、upper_bound()、binary_search()
由于笔者比较懒,所以把分治算法(二分查找篇)和STL第五弹放在一起。。。
Part 1:引入和导语
Part 2:怎么写二分查找函数!
//这里指的左指针和右指针指向的是答案范围的最小值和最大值,初始时指向0和数组的最后一个元素
#include
Part 3:STL二分函数
#include
Part 4:实战演练
//1240
//#include
上一篇:VBA操作WORD(〇)自动智能排版、格式化公文模板
下一篇:C语言的灵魂(函数)
文章标题:分治算法(1)——二分查找、STL函数库的应用第五弹——二分函数
文章链接:http://soscw.com/index.php/essay/52152.html