很想写一个很好的文章引子,但是囿于语文水平有限,写不出什么好东西来,干脆就随便写点东西吧。之前写的文章都是关于爬虫的,爬虫虽好,但是写来写去就是那些东西,是时候学习点新东西了!现在自己很缺关于算法的知识,于是就上计蒜客学习了基础算法入门,但是苦于它教学用的是C++,而我大一学过C++,现在早就忘光了。于是我将写几篇系列文章,将计蒜客上面的C++算法改写成Python。
这是第一篇文章《二分查找》
以下文字摘自计蒜客
二分查找,也叫做二分搜索法,是通过不断缩小解可能存在的范围,从而求得问题最优解的方法。接下来,我来带大家学习如何实现二分查找算法。二分查找一般要着重确认在有序数组或序列中找不到给定值、或者待查数组中有重复元素时对计算结果的要求。
这次我们来实现的题目是,给定一个单调非递减数组,和一个要插入的元素,算出它应该插入的位置。比如一个数组{1, 3, 4, 5, 7, 8, 8, 9, 10, 13},如果要插入的元素是6,那么就应该放在现在7所在的位置;如果是8,就应该放在第一个8所在的位置;如果是14,则应该放在13的后面。
代码已经实现了整体的框架,下面来跟随我一步步实现算法的核心代码。首先我们进入binary_search的函数内部,第一行代码定义了二分查找常用的三个变量:left, right和mid。
之后我们会不断缩小left到right之间的距离,减少可行区间的范围,直到left和right相等时就是我们所需要的结果。<span style="font-size:18px;">int left = 0, right = len - 1, mid;</span>
第一步:请在while循环之后的第一行计算更新mid的值。特别提醒:二分查找的实现方法并不唯一,我们在这里只是举一个实现的例子,请读者尽可能跟随我的思路,将代码的空缺处逐步完善。
第二步:算出mid的位置后,我们需要判断要去左半部分继续计算还是去右半部分继续计算。由于输入的数组是单调非递减的,也就是后面的元素一定不会比前面的小,那么我们首先就要比较mid位置的元素与待查元素的大小关系。接下来我们要实现if语句的逻辑,当待查元素比中间元素不大时修改right的值。
第三步:实现了去左半部分继续查找的逻辑之后,我们继续实现右半部分的逻辑。紧接着刚才的if语句,我们用else代码块和修改left值来实现期望的逻辑。
第四步:我们已经实现了大部分的二分查找的逻辑,left就是计算的结果。接下来我们继续处理边界情况。如果待查元素超过数组中的最大值时,返回的下标应该是数组最后一个下标的靠后一个位置。我们需要比较待查元素和数组最后一个元素的大小,如果待查元素更大的话需要将left结果加1。
用if语句实现这个逻辑吧。
恭喜你!你已经实现了一个基本的二分查找算法。
二分查找的具体实现细节往往和题目的要求相关,读者要多多进行二分查找相关题目的练习,只有彻底理解二分的思想才能以不变应万变,正确实现各种姿势的二分查找哈。
下面就直接贴我改写的Python代码了:
#给定一个从小到大排序的列表num,再给定一个数字target,让你指出这个target该在num的哪个位置?索引从0开始
num=[1, 3, 4, 5, 7, 8, 8, 9, 10, 13,16,18,22] def binary(num,target): m=len(num) left=0;right=m-1;mid=0 while left<right: mid=(left+right)/2 #与中间的数对比大小 if target<=num[mid]: #如果target比中间数小,说明target在num的左半部分 right=mid #所以右边大数改为原来num的中间数 else: left=mid+1 #同上 if target>num[m-1]: #如果target比num最大的数还大,则输出为m-1 left+=1 #也可以为left=m return left print binary(num,17)#输出11,排在16和18之间
over。