• 二分查找法


    二分查找方法
    二分查找经常用来在有序的数列查找某个特定的位置。

    因此,应用二分查找法,这个数列必须包含以下特征:

    • 存储在数组中
    • 有序排列

    二分查找方法不适用于链表,因为链表方法需要遍历,应用二分查找法意义不大。

    一般情况下,我们默认数组是单调递增数列,且无重复元素。(有重复元素的题应该如何解决)

    二分查找方法递归和非递归实现

     第一种是递归方法实现,递归方法一般走的比较深,容易超时:

     1 public int binarySearch(int [] A, int low, int high, int target){
     2     if (low > high)
     3         return -1;
     4 
     5     int mid = (low + high)/2;
     6     if (A[mid]> target)
     7         return    binarySearch(array, low, mid -1, target);
     8     if (array[mid]< target)
     9         return    binarySearch(array, mid+1, high, target);
    10     
    11     if (A[mid] == target)
    12         return mid;
    13 }           

     第二种是非递归实现方法,更常用一些:

     1 public int binarySearch(int[] A, int low, int high, int target){
     2     if(low > high)
     3         return -1;
     4 
     5     while(low<=high){
     6         int mid = low+high/2;
     7         if(A[mid] == target)
     8             return mid;
     9         if(A[mid] > target)
    10             high = mid-1;
    11         if(A[mid] < target)
    12             low = mid+1;
    13     }
    14     return -1;
    15 }

    Rotated Sorted Array

    这是二分查找方法的一个变种,在leetcode中出现过。

    它是有序数组,取期中某一个数为轴,将其之前的所有数都轮转到数组的末尾所得。比如{7, 11, 13, 17, 2, 3, 5}就是一个轮转后的有序数组。非严格意义上讲,有序数组也属于轮转后的有序数组——我们取首元素作为轴进行轮转。 

     1 public int SearchInRotatedSortedArray(int [] array, int low, int high, int target) 
     2 {
     3     while(low <= high)
     4     {
     5         int mid = (low + high) / 2;
     6         if (target < array[mid])
     7             if (array[mid] < array[high])//the higher part is sorted
     8                 high = mid - 1; //the target would only be in lower part
     9             else //the lower part is sorted
    10                 if(target < array[low])//the target is less than all elements in low part
    11                     low = mid + 1;
    12                 else
    13                     high = mid - 1;
    14 
    15         else if(array[mid] < target)
    16             if (array[low] < array[mid])// the lower part is sorted
    17                 low = mid + 1; //the target would only be in higher part
    18             else //the higher part is sorted
    19                if (array[high] < target)//the target is larger than all elements in higher part
    20                     high = mid - 1;
    21                 else
    22                     low = mid + 1;
    23         else //if(array[mid] == target)
    24             return mid;
    25     }
    26 
    27     return -1;
    28 }

    二分查找缺陷

    二分查找法的O(log n)让它成为十分高效的算法。不过它的缺陷却也是那么明显的。就在它的限定之上:

    有序,我们很难保证我们的数组都是有序的。当然可以在构建数组的时候进行排序,可是又落到了第二个瓶颈上:它必须是数组。

    数组读取效率是O(1),可是它的插入和删除某个元素的效率却是O(n)。因而导致构建有序数组变成低效的事情。

    解决这些缺陷问题更好的方法应该是使用二叉查找树了,最好自然是平衡二叉树了,自能高效的(O(n log n))构建有序元素集合,又能如同二分查找法一样快速(O(log n))的搜寻目标数。

    二分查找其他应用

    1. 寻找上下界

    2. 寻找范围

    本文基于:http://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html

  • 相关阅读:
    Undo/Redo的C#实现方式
    c#中@符号作用
    面向对象理解随笔
    C# 面向对象定义常量,属性,方法
    c# 字段和属性
    面向对象思想
    用C表达面向对象语言的机制——C#版
    判断生日
    查找字符
    被7整除
  • 原文地址:https://www.cnblogs.com/springfor/p/3857646.html
Copyright © 2020-2023  润新知