變形遞增數(shù)列的二分查找算法

Q

一個遞增數(shù)列把后幾項整體移動到最前面,移動幾項并不知道,例如:數(shù)列123456789,移動后3項,數(shù)列變?yōu)?89123456。對于這樣的數(shù)列,給定一個數(shù),查找該數(shù)在數(shù)列中的下標,如果不存在則返回-1。

A

算法分析

對于一個有序的數(shù)組,最快的是二分查找,時間復雜度是θ(logn)。本題只是二分查找的一個變形,所以可以以二分查找為基礎,寫出算法。

本題的關鍵是如何進行正確的遞歸,也就是判斷key在哪一半中。函數(shù)newBs中對6種情況分別進行了判斷,之后調用newBs或者bs進行遞歸。因為每一次遞歸只有常數(shù)次判斷,所以最終的時間復雜度和二分查找是一樣的,均是θ(logn)

C++實現(xiàn)

#include <iostream>
using namespace std;

int bs(const int *arr, int low, int high, int key)
{       
    int mid = low+(high-low)/2;
    if (low > high) {
        return -1;
    }
    if (arr[mid] == key) {
        return mid;
    } else if (arr[mid] > key) {
        return bs(arr, low, mid-1, key);
    } else
        return bs(arr, mid+1, high, key);
}

int newBs(const int *arr, int low, int high, int key)
{
    if (low > high)
        return -1;
    int mid = low+(high-low)/2;
    if (arr[mid] == key)
        return mid;
    if (arr[high] == key)
        return high;
    if (arr[low] == key)
        return low;
    
    if (key > arr[high]) {
        if (key < arr[mid]) {
            return bs(arr, low, mid-1, key);
        } else if (arr[mid] > arr[high]) {
            return newBs(arr, mid+1, high, key);
        } else {
            return newBs(arr, low, mid-1, key);
        }
    } else {
        if (key > arr[mid]) {
            return bs(arr, mid+1, high, key);
        } else if (arr[mid] < arr[high]) {
            return newBs(arr, low, mid-1, key);
        } else {
            return newBs(arr, mid+1, high, key);
        }
    }
}

int main(int argc, const char * argv[])
{
    const int arr[] = {10,11,16,1,2,3,4,5,6,7,8,9};
    int length = sizeof(arr)/sizeof(int);
    
    for (int i = 0; i < length; i++) {
        int result = newBs(arr, 0, length-1, arr[i]);
        cout << "result: " << result << endl;
    }

    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容