基础算法之二分查找总结

本博客是我在做题和看书遇到各种情况的总结。

参考了书,邓俊辉老师编写的《数据结构(C++语言版)(第3版)》,同时还有网友的总结(以下会给出相应的链接)。

 一、查找等于目标元素的位置(若是多个,只要求找到即可)

 1 /二分查找的主体
 2 int binarySearch(int A[], int n, int target)
 3 {
 4     int lo = 0, hi = n;  //n为数组的A元素的个数
 5
 6     while (lo < hi)
 7     {
 8         int mid = lo + (hi - lo)/2;
 9         if (A[mid] == target)
10             return mid;
11         else if (target < A[mid])
12             hi = mid;
13         else
14             lo = mid + 1;
15     }
16     return -1;
17 }

这里关于右边界hi的取值值得注意的有几点:

1)在while循环外面的hi=n,说明是前开后闭型([0,n) ),那么在while循环中的hi的取值应构成前开后闭型([ lo,mid )),此时while循环的条件为lo<hi

2)在while循环外面的hi=n-1,说明是前开后闭型([0,n-1]),那么在while循环中的hi的取值应构成前开后闭型([ lo,mid-1]),此时while循环的条件为lo<=hi 

这里不是说,其他情况下的使用,就不能使用,只是有时候会出错。

二、查找重复元素的第一个值的下标,若是没有重复元素则返回第一个不小于目标值的下标

 1 //二分查找的主体
 2 int binarySearch(int A[], int n, int target)
 3 {
 4     int lo = 0, hi = n;
 5
 6     while (lo < hi)
 7     {
 8         int mid = lo + (hi - lo)/2;
 9
10         if (A[mid] < target)
11             lo = mid + 1;
12         else
13             hi = mid;
14     }
15     return hi;
16 }

:这里的hi值也可以像一种那样变化,要对应的变化。只不过这样改变以后,在不存在目标值的情况下,返回的是第一个小于目标值(从目标值往左数)的下标。

三、查找重复元素的最后一个下标,或者不存在目标值时,第一个小于目标值的下标。这种情况,邓老师书上有严格的证明。

 1 //二分查找的主体
 2 int binarySearch(int A[], int n, int target)
 3 {
 4     int lo = 0, hi = n;
 5
 6     while (lo < hi)
 7     {
 8         int mid = lo + (hi - lo)/2;
 9
10         if (A[mid] <= target)
11             lo = mid + 1;
12         else
13             hi = mid;
14     }
15     return --lo;    //必须减减
16 }

注意:第二种和第三种的区别在于if条件判断语句的差别,和返回值的区别,

四、将二、三结合就可以求出存在多个目标值时,目标值所在的区间。详情见search for a range

版本一的进化版是斐波那契查找,这和二分查找的主要区别在于中间点mid是使用斐波那契进行选择的,版本三的各分支的平均查更好些,详情请见参考书。

总结

针对二分查找,值得注意的是区间的选取(见第一种情况下的说明);要是求目标值给定条件下(第一个或最后一个)下的下标,可以通过变化while循环中的if条件内的等号所在来实现。

下面给出第三种情况下测试程序,第一、二中可以通过变化数组A所含的值来实现。

 1 #include<iostream>
 2 #include<vector>
 3
 4 using namespace std;
 5
 6 int binarySearch(int A[], int n, int target);
 7
 8 int main()
 9 {
10     int A[] = { 0,1,2,3,4,4,4,4,5,6,7,8,9 };
11     int target = 4;
12     int res = binarySearch(A, 13, target);
13     cout << "目标值的下标是:" << res << endl;
14     return 0;
15 }
16
17 //二分查找的主体
18 int binarySearch(int A[], int n, int target)
19 {
20     int lo = 0, hi = n;
21
22     while (lo < hi)
23     {
24         int mid = lo + (hi - lo)/2;
25
26         if (A[mid] <= target)
27             lo = mid + 1;
28         else
29             hi = mid;
30     }
31     return --lo;    //必须减减
32 }
33
34
35 /*
36     int A[] = { 0,1,2,3,4,4,4,4,5,6,7,8,9 },target=4时,返回值为7
37     int A[] = { 0,1,2,4,4,4,4,5,6,7,8,9 },target=3时,返回值为2
38     int A[] = { 0,1,2,4,4,4,4,5,6,7,8,9 },target=3,返回lo时,返回值为3
39 */

若是各位看官发现什么问题,多多留言哈,共同进步~

参考:

http://www.61mon.com/index.php/archives/187/

http://blog.csdn.net/sunmenggmail/article/details/7540970

http://www.cnblogs.com/luoxn28/p/5767571.html

http://www.cnblogs.com/grandyang/p/6854825.html

时间: 2024-07-30 00:25:00

基础算法之二分查找总结的相关文章

基础算法介绍 —— 二分查找算法

不知不觉在目前的公司待满3年了,打算回家找份工作.面试中被问到关于算法的题目:有哪些常见的查找算法?下来就把我所掌握的查找算法分享给大家,本文主要介绍二分查找算法. 算法定义(摘自百度):二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果

基础算法之二分查找

二分查找 利用分治法,逐渐苏小查找范围,适用于有序数组. 时间复杂度是O(log2N). PS:二分查找算法的判定过程实际上可以借助一棵平衡二叉树来描述,中间位置的关键字可以看成二叉树的根节点. C++代码如下: 1 #include <iostream> 2 using namespace std; 3 template<class DataType> int binSearch(DataType key[],int n,DataType k) 4 { 5 int low=0,h

查找算法:二分查找、顺序查找

08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活.此系列是对四年专业课程学习的回顾,索引参见:http://blog.csdn.net/xiaowei_cqu/article/details/7747205 查找算法 查找算法是在存在的序列(list) 中查找特定的目标(target),要求序列中每个记录必须与一个关键词(key)关联才能进行查找. 查找算法通常需要两个输入: 1.被查找的序列 2.要查找的关键词 查找算法的输出参数和返回值: 1.返回类型为 Error_co

【数据结构与算法】二分查找

基本思想 首先将给定的值K与表中中间位置元素比较,若相等,则查找成功:若不等,则所需查找的元素只能在中间数据以外的前半部分或者后半部分,缩小范围后继续进行同样的查找,如此反复,直到找到为止. 代码实现 /** * 源码名称:BinarySearch.java * 日期:2014-08-14 * 程序功能:二分查找 * 版权:[email protected] * 作者:A2BGeek */ public class BinarySearch { public static int binaryS

算法系列&lt;二分查找&gt;

二分查找又称折半查找,是针对有序顺序表的查找,前提:数据是顺序存储的,已经按照关键词进行升序排序.查找成功返回索引值,查找不成功返回-1. 下面用java来实现二分查找算法: /** * 二分查找:针对已排好序的序列,查找成功返回所在位置的索引值,查找不成功返回-1 * 查找的最好时间复杂度:O(1),最坏时间复杂度O(logN),平均时间复杂度:O(logN) * 测试case: * case1:{1} 查找1 * case2:{1} 查找2 * case3:{} 查找1 * case4:{1

算法学习——二分查找(折半查找)

算法学习--二分查找 注意点 1. 二分查找的前提是有序的数组 2. 建议使用[start,end)的区间寻找,符合规范 3. 使用的是递归法 递归的人口 private static int find(int[] temp, int x) { //如果要查找的数x比数组的最后一个数要大,则找不到数值,返回-1 if (x > temp[temp.length - 1]) { return -1; } return find(temp, 0, temp.length, x);//进入递归 } 递

常见算法之二分查找

1.算法思想 二分查找采用分而治之的思想.要求被查找的集合必须是有序的.主要思路: 根据起始位置和结束位置,确定中间位置. 拿目标值与中间位置的值做比较,假如目标值大于中间位置取值,则起始位置为中间位置加1. 假如目标值小于中间位置取值,则结束位置为中间位置减1. 直至起始位置小于等于结束位置,找到目标值的位置即索引. 2.代码实现 2.1.基于Python3.x实现 代码如下: 1 #coding:utf-8 2 def half_search(lst,key): 3 start = 0 4

算法:二分查找(基础)

二分查找是一个基础的算法,也是面试中常考的一个知识点. 基础二分查找 二分查找就是将查找的键和子数组的中间键做比较,如果被查找的键小于中间键,就在左子数组继续查找:如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素. /** * 二分查找,找到该值在数组中的下标,否则为-1 */ static int binarySerach(int[] array, int key) { int left = 0; // 左边开始位置的下标 int right = array.length - 1;

二分算法入门——二分查找

二分查找,无论是从名字还是理论都十分简单一个算法,其博大精深,简直恐怖.Jon Bentley:90%以上的程序员无法正确无误的写出二分查找代码. 别人不知道,反正我早上是写了好久,这个查找算法,将查找的复杂度从 o( n ) 降到了 o( logn ) ,当之无愧的的好算法,更是许多高级算法的优化策略之一. 二分查找之基本思路 虽然二分查找是一个很吊的算法,但是跟很多算法一样,需要使用的基础条件——序列有序! 先假设一个单调非增序列:1 2 3 4 5 6 ,求找到3的位置,地球人都会马上这么