二分查找(面試必備)

原文:https://subetter.com/algorith...html

  在計算機科學中,二分搜索(binary search),也稱折半搜索(half-interval search)、對數搜索(logarithmic search),是一種在有序數組中查找某一特定元素的搜索算法。搜索過程從數組的中間元素開始,若是中間元素正好是要查找的元素,則搜索過程結束;若是某一特定元素大於或者小於中間元素,則在數組大於或小於中間元素的那一半中查找,並且跟開始同樣從中間元素開始比較。若是在某一步驟數組爲空,則表明找不到。這種搜索算法每一次比較都使搜索範圍縮小一半。c++

問題1

給定一個有序的數組,查找value是否在數組中,不存在返回-1。git

int BinarySearch(int array[], int n, int value)
{
    int left = 0;
    int right = n - 1;
    //若是這裏是int right = n 的話,那麼下面有兩處地方須要修改,以保證一一對應:
    //一、下面循環的條件則是while(left < right)
    //二、循環內當 array[middle] > value 的時候,right = mid

    while (left <= right)  //循環條件,適時而變
    {
        int middle = left + ((right - left) >> 1);  //防止溢出,移位也更高效。同時,每次循環都須要更新。
        if (array[middle] > value)
            right = middle - 1;  //right賦值,適時而變
        else if (array[middle] < value)
            left = middle + 1;
        else
            return middle;
        //可能會有讀者認爲剛開始時就要判斷相等,但畢竟數組中不相等的狀況更多
        //若是每次循環都判斷一下是否相等,將耗費時間
    }
    return -1;
}

問題2

給定一個有序的數組,查找value第一次出現的下標,不存在返回-1。github

int BinarySearch(int array[], int n, int value)
{
    int left = 0;
    int right = n - 1;

    while (left <= right)  
    {
        int middle = left + ((right - left) >> 1);
        if (array[middle] >= value)  //由於是找到最小的等值下標,因此等於號放在這裏
            right = middle - 1;
        else
            left = middle + 1;
    }
    return array[right + 1] == value ? right + 1 : -1;
}

若是問題改成查找value最後一次出現的下標呢?只需改動兩個位置:
1.if (array[middle] >= value)中的等號去掉;
2.returnright+1改成left-1算法

問題3

給定一個有序的數組,查找最接近value且大於value的數的下標(若是該數存在多個,返回第一個下標),不存在返回-1。數組

int BinarySearch(int array[], int n, int value)
{
    int left = 0;
    int right = n - 1;

    while (left <= right)  
    {
        int middle = left + ((right - left) >> 1);
        if (array[middle] > value)
            right = middle - 1;
        else
            left = middle + 1;
    }
    return array[right + 1] > value ? right + 1 : -1;
}

若是問題改成查找最接近value且小於value的數的下標(若是該數存在多個,返回最後一個下標)呢?只需改動兩個位置:
1.if (array[middle] > value)加入一個等號;
2.return array[right + 1] > value ? right + 1 : -1;改成return array[left-1] < value ? left - 1 : -1;code

總結

  二分算法所操做的區間,是左閉右開,仍是左閉右閉,須要在循環體跳出判斷中,以及每次修改left,,right區間值這兩個地方保持一致,不然就可能出錯。htm

參考文獻:
[ 1 ] 二分搜索算法. Wikipedia.
[ 2 ] July. 有序數組的查找ip

相關文章
相關標籤/搜索