二分查找

来源:互联网 发布:我打软件技巧 编辑:程序博客网 时间:2024/06/05 03:24

上次面试栽到了二分查找,最简单的问题上,以至于一直不想面对,但是不论怎样,还是要不断成长,不断提升,不会的东西就要不断提升,才能得到真正想要的东西。

好啦,回归正题,二分查找又叫二分查找,它的前提是线性表中的记录必须是有序的,通常常见的就是由小到大排序,查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区查找。不断重复上述过程,直到查找成功,或者所有查找区域无记录,查找失败为止。

(1)先来看最基础时候的情况:

int binary_search(int *a, int n, int key){int low, high, mid;low = 0; high = n;while (low <= high){mid = (low + high) / 2;if (key < a[mid]){high = mid - 1;}else if (key > a[mid]){low = mid + 1;}elsereturn mid;}return 0;}
(2)当然有很多变形的情况啦,咱们先来看第一种,还是有序数组,但是数字有重复,具体有几个重复不知道,现在要求是要找到第一个出现的位置。

这个题第一次并没有多少想法,甚至记得刷过剑指offer上的内容,当时想着定义一个哈希表,哈希表的键值是字符,而值就是该字符出现的次数,其实题意完全不相关,也是佩服自己当时为什么会那么想,这个题其实可以这么想,既然要找第一次出现的某个数,而且这个数也有可能重复,那我其实让它停止的条件可以是判断第一个小于当前值的下标,那么再判断这个下标加上1是否小于数组的长度,如果小于数组的长度,ok那么最终的输出就是要求的输出。

int mid;int binary_search(int *a, int n, int key,int &low){int high;low = 0; high = n;while (low <= high){mid = (low + high) / 2;if (key <=a[mid]){high = mid - 1;}elselow = mid + 1;}return low<n ?low:-1;}
这样返回的low值就是最终要求的输出,返回的最终值就是加1之后的结果。

(3)第三种情况,找到重复数字最后一个出现的位置。这种情况跟第二种情况同理,其实我们要找的就是第一个大于这个数的位置,那么最终输出的位置就是当前位置减去1,再去判断减去1之后是不是大于-1,大于那么OK。

int mid;int binary_search(int *a, int n, int key,int &low){int high;low = 0; high = n;while (low <= high){mid = (low + high) / 2;if (key <a[mid]){high = mid - 1;}elselow = mid + 1;}return (low-1>0 && (a[low-1]==key))?low-1:-1;}
注意if条件里只要小于mid值那么一直进行这样的操作,所以最后返回的结果就是减去1之后的结果。

(4)查找数组中第一个大于某个数的最小标,其实跟3的情况一样,就是返回的值不一样,返回的值就不需要减去1了,返回为

return low<=n?low:-1;
(5)查找数组中第一个小于某个数的最大标,跟2的情况很像,只是返回值变下,因为(2)的思想最终加了1,所以最终输出的时候记得减去1,输出代码为:

return (low - 1 >= 0) ? low - 1 : -1;
(6)对于判断一个数组中某个数的出现次数,其实是可以调用上述的函数,先求一个数第一次出现的位置记为first,再记录最后一个出现的位置就为last,那么出现的次数就是last-first+1啦。

变形的还有很多很多,学习的道路很长很长,加油吧,参考这篇文章写的,具体也可以参考这篇。



0 0