二分查找(binary search)

来源:互联网 发布:js判断滚动条是否存在 编辑:程序博客网 时间:2024/04/26 05:59

二分查找(binary search)

二分查找对于学过数据结构或者算法的人来说,应该是非常熟悉的。其基本思想是:比较目标(target)和中间关键字的大小关系,如果二者相等,则查找完毕;如果二者不等,则可以根据二者的大小关系,将查找的范围减半。

虽然二分查找的算法很简单,但是对于一个code新手来说,正确无误地实现一个二分查找算法也不是那么容易的。

最近,刷了几道二分查找的题目,将刷题的一点收获整理如下:

1.二分查找算法适用的范围:

①必须是顺序表,不适用于链式存储
②查找之前,序列必须是有序的。对于无序的序列,可以先采用合适的排序算法进行排序后,再使用二分查找。

2.二分查找算法的基本模式:

递归方式:

int binary_search(const int[] arr,int start,int end,int khey){    if(start > end)        return -1;    int mid = start + (end - start) / 2;    if(arr[mid] > khey)        return binary_search(arr,start,mid-1,khey);    if(arr[mid] < khey)        return binary_search(arr,mid+1,end,khey);    return mid;//最后检测相等是因为大多数情况下是小于或者大于}

非递归方式:(更常用)

int binary_search(const int[] arr,int start,int end,int khey){    int mid;    while(start <= end){        mid = start + (end - start) / 2;        if(arr[mid] < khey)            start = mid +1;        else if(arr[mid] > khey)            end = mid - 1;        else             return mid;    }    return -1;}

其中,需要注意的地方有:
① 我们学习二分算法的时候,求mid可能会用:mid = (start + end)/2,这时,在计算start+end的时候,可能会产生溢出,故以上所写的两种方式,均采用start + (end - start) / 2的方式,有时候可以避免溢出。
②在非递归算法中,while循环中究竟应该是(start < end)还是(start <= end),这应该具体情况具体分析;
③对于mid和khey比较的三种情况(大于,小于,相等)的排列顺序,大多数情况下,是影响不大的,实际中,可以根据三种情况出现的概率,决定其顺序;
④以上仅仅是二分查找算法的模板,具体使用时应该具体情况具体分析,灵活运用。

3.二分查找的复杂度

时间复杂度:O(logn)
空间复杂度:O(1)

在有些地方你可能会看到三分查找(ternary search),三分查找基本思想和二分查找一致,具体来讲:每次选出三分之一点和三分之二点,而不是中点,然后比较target和这两个点的大小关系,从而将查找的范围缩小至原来的三分之一。

二分查找和三分查找的空间复杂度都是O(1),而二分查找的时间复杂度是O(log2n),三分查找的时间复杂度是O(log3n)。既然三分查找的时间复杂度要优于二分查找,那我们为什么不经常使用三分查找,而经常使用二分查找呢?原因在于在最坏情况下,三分查找要明显劣于二分查找。这个具体的推导过程就不详述了, 想了解的可以参考这道题目。

原创粉丝点击