算法之二分查找Binary Search

 二分查找

一、二分查找简介

        二分查找又称折半查找,

            优点 : 比较次数少,查找速度快,平均性能好;

            缺点 : 要求待查表为有序表,且插入删除困难。

            因此,折半查找方法适用于不经常变动查找频繁有序列表

            具体步骤 :

                    首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较 ; 如果两者 相 等, 则 查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。


下面是二分查找的递归代码和非递归代码:

//递归
int BinSearch(int Array[],int low,int high,int key)
{
      if (low<=high)
      {
           int mid = (low+high)/2;
           if(key == Array[mid])
                 return mid;
           else if(key<Array[mid])
                 return BinSearch(Array,low,mid-1,key);
           else if(key>Array[mid])
                 return BinSearch(Array,mid+1,high,key);
      }
      else
           return -1;
}  

//非递归 
 int BinSearch(int Array[],int SizeOfArray,int key)  
{  
    int low=0,high=SizeOfArray-1;  
    int mid;  
    while (low<=high)  
    {  
        mid = (low+high)/2;  
        if(key==Array[mid])  
            return mid;  
        if(key<Array[mid])  
            high=mid-1;  
        if(key>Array[mid])  
            low=mid+1;  
    }  
    return -1;  
}



二、时间复杂度分析     

        二分查找的基本思想 :

                    将n个元素分成大致相等的两部分,去a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.

        时间复杂度无非就是while循环的次数!

        总共有n个元素,渐渐跟下去就是n,n/2,n/4,....n/2^k,其中k就是循环的次数

         由于你n/2^k取整后>=1

         即令n/2^k=1

         可得k=log2n,(是以2为底,n的对数)

    所以时间复杂度可以表示O()=O(logn)

    说的简单点就是每次剔除一般的元素,最坏情况下需要k次查找完成,那么 2^k=n  ---> k=log(n)

三、算法实例     

                以下实例均来自leetcode,算法实现中需要注意的地方会有 注视星号(//****)

/* 
Search Insert Position
     Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
     You may assume no duplicates in the array.
     Here are few examples.
        [1,3,5,6], 5 → 2
        [1,3,5,6], 2 → 1
        [1,3,5,6], 7 → 4
        [1,3,5,6], 0 → 0  
    题目意思:给定一个已排序数组和target目标,找出应该将target插入数组哪个位置
*/
public class Solution {
    public int searchInsert(int[] nums, int target) {
        if(nums.length==0){//****
            return 0;
        }
    int start=0;
    int end= nums.length-1;
    while(start<=end){     //****       
        int mid = (start + end)/2;
        if(nums[mid]==target){
            return mid;
        }else if(nums[mid]<target){
            start=mid+1;
        }else{
            end=mid-1;
        }         
    }
          return start;//*****
    } 
}

/*Search for a Range
    Given a sorted array of integers, find the starting and ending position of a given target value.
    Your algorithm's runtime complexity must be in the order of O(log n).
    If the target is not found in the array, return [-1, -1].
    For example,
    Given [5, 7, 7, 8, 8, 10] and target value 8,
    return [3, 4]. 
    题目:给定一个已排序数组,该数组中有重复元素 ,给一个target目标,找出这个target的起始位置.
*/
 //Solution one  :递归+二分
public class Solution {
    public int[] searchRange(int[] A, int target) {
        int[] range = {A.length, -1};
        searchRange(A, target, 0, A.length - 1, range);//****
        if (range[0] > range[1]) range[0] = -1; 
        return range;
    }
 
    public void searchRange(int[] A, int target, int left, int right, int[] range) {
        if (left > right) return;//****
        int mid = left + (right - left) / 2;
        if (A[mid] == target) {
            if (mid < range[0]) {
                range[0] = mid;
                searchRange(A, target, left, mid - 1, range);//****
            }
            if (mid > range[1]) {
                range[1] = mid;
                searchRange(A, target, mid + 1, right, range);//****
            }
        } else if (A[mid] < target) {
            searchRange(A, target, mid + 1, right, range);
        } else {
            searchRange(A, target, left, mid - 1, range);
        }
    } 
} 

  //Solution two:
public class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res={-1,-1};
        int rangeS;
        int rangE;
        if(nums.length==0){
            return res;
        }
        int start =0;
        int end = nums.length-1;
        while(start<=end){
            int mid = start+(end-start)/2;
            if(nums[mid]==target){//****
                rangeS=rangE=mid;
                while(nums[num1]==target){
                    rangeS--;
                    if(rangeS<0){
                        break;
                    }
                }
                while(nums[rangE]==target){
                    rangE++;
                    if(rangE>nums.length-1){
                        break;
                    }
                }
                res[0]=rangeS+1;
                res[1]=rangE-1;
                return res;
            }else if(nums[mid]<target){
                start=mid+1;
            }else{
                end= mid-1;
            }
        }
        return res;
    }   
} 
/*
solution two 说明:     
    找了任意一个target目标,其他目标必定在其周围,直接向左和向右遍历知道不是target目标,记下下标即可. 
    此方法的问题:当数组和target数量非常巨大的时候,这中挨个的遍历十分耗时!.相当于小范围的顺序查找.时间复杂度与target个数有关,     
    总的时间复杂度: log(n)+m;  n为数组大小,m为target目标的个数 
  
*/

/*Search in Rotated Sorted Array
    Suppose a sorted array is rotated at some pivot unknown to you beforehand.
    (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
    You are given a target value to search. If found in the array return its index, otherwise return -1.
    You may assume no duplicate exists in the array. 
    题目意思: 给定一个被翻转过的数组(原数组有序),找到给定target目标的位置.
*/
public class Solution {
    public int search(int[] A, int target) {
         int left = 0, right = A.length - 1;
         while( left <= right){/****
             int mid = (left + right)/2;
             if(A[mid] == target) return mid;
             if(A[left] < A[mid]){
                 if(target <= A[mid] && target >= A[left])//****
                     right = mid - 1;
                 else left = mid + 1;
             } else if (A[left] > A[mid]){
                 if(target >= A[left] || target <= A[mid]){//****
                     right = mid -1;
                 else  left = mid + 1; 
             }
             else left ++;
         }
         return -1;
        }
    }

/* 
Search a 2D Matrix
    Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
    Integers in each row are sorted from left to right.
    The first integer of each row is greater than the last integer of the previous row.
    For example,
    Consider the following matrix: 
    [
      [1,   3,  5,  7],
      [10, 11, 16, 20],
      [23, 30, 34, 50]
    ]
    Given target = 3, return true.  
*/
 public class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        //先考虑边界情况
        if (matrix == null || matrix.length == 0) {
            return false;
        }
        if (matrix[0] == null || matrix[0].length == 0) {
            return false;
        }
 
        int row = matrix.length, column = matrix[0].length;
        int start = 0, end = row * column - 1;
 
        while (start <= end) {
            int mid = start + (end - start)/2;
            int number = matrix[mid / column][mid % column];
            if (number == target) {
                return true;
            } else if (number < target) {
                start = mid+1;
            } else {
                end = mid-1;
            }
        }
        return false;
    }
}
/*算法思路:将整个2维数组看做一个需要进行二分查找的整体,确定整体的开始和结束,按照一般二分查找进行查找.*/

    第一篇博文 , 拼凑了95% ,first day! 

转载于:https://my.oschina.net/dadou/blog/478899

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A binary search algorithm (or binary chop) is a technique for finding a particular value in a sorted list. It makes progressively better guesses, and closes in on the sought value, by comparing an element halfway with what has been determined to be an element too low in the list and one too high in the list. A binary search finds the median element in a list, compares its value to the one you are searching for, and determines if it’s greater than, less than, or equal to the one you want. A guess that turns out to be too high becomes the new top of the list, and one too low the new bottom of the list. The binary search's next guess is halfway between the new list's top and bottom. Pursuing this strategy iteratively, it narrows the search by a factor 2 each time, and finds your value. A binary search is an example of a divide and conquer algorithm (more specifically a decrease and conquer algorithm) and a dichotomic search (more at Search algorithm). The most common application of binary search is to find a specific value in a sorted list. To cast this in the frame of the guessing game (see Example below), realize that we are now guessing the index, or numbered place, of the value in the list. This is useful because, given the index, other data structures will contain associated information. Suppose a data structure containing the classic collection of name, address, telephone number and so forth has been accumulated, and an array is prepared containing the names, numbered from one to N. A query might be: what is the telephone number for a given name X. To answer this the array would be searched and the index (if any) corresponding to that name determined, whereupon it would be used to report the associated telephone number and so forth. Appropriate provision must be made for the name not being in the list (typically by returning an index value of zero), indeed the question of interest might be only whether X is in the list or not. If the list of names is in sorted order, a binary search will find a given name with far fewer probes than the simple procedure of probing each name in the list, one after the other in a linear search, and the procedure is much simpler than organising a hash table though that would be faster still, typically averaging just over one probe. This applies for a uniform distribution of search items but if it is known that some few items are much more likely to be sought for than the majority then a linear search with the list ordered so that the most popular items are first may do better. The binary search begins by comparing the sought value X to the value in the middle of the list; because the values are sorted, it is clear whether the sought value would belong before or after that middle value, and the search then continues through the correct half in the same way. Only the sign of the difference is inspected: there is no attempt at an interpolation search based on the size of the differences. Your task is to write a program that, given a set numbers of ascending and a key, finding a particular postion in a sorted list.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值