二分查找算法的應用


二分查找算法

 

 1.旋轉數組中的最小數字:(3,4,5,1,2 為 1,2,3,4,5 的一個旋轉)

 

正如上圖所示:我們計算中間的位置 middle 如果說 arr[middle] >= arr[start] 說明 middle 落在了前面的遞增區間上,middle = start 縮小查找范圍.

同理,如果arr[middle] <= arr[end] 則將 end = middle

這里呢有一個問題:

int MinInorder(int* arr, int start, int end)
{
    int result = arr[start];
    bool check = false;
    while (start <= end)
    {
        ++start;
        if (arr[start] < result)
            return arr[start];
    }
    return result;
}

int Min(int* arr, int lenth)
{
    if (arr == NULL || lenth <= 0)
    {
        cout << "Error:Invalid Parameters" << endl;
        return 0;
    }
    int start = 0, middle, end = lenth - 1;
    while (start < end)
    {
        middle = (end - start) / 2 + start;
        if (end - start == 1)
            return arr[end];
        if (arr[middle] == arr[start] && arr[middle] == arr[end])
            return MinInorder(arr + start, start, end);
        if (arr[middle] >= arr[start])  //非特例情況下
            start = middle;
        else
            end = middle;
    }
}

 

 

2.旋轉數組中查找某一個數:(7,8,9,1,2,3,4,5,6 中找 1 返回 3

 

 

int Inorder(int* arr, int left, int right,int key)
{
    for (int i = left; i <= right; ++i)
    {
        if (arr[i] == key)
            return i;
    }
    return -1;
}

int BinarySearch(int* arr, int left, int right, int key)
{
    if (left <= right)
    {
        int middle = (right - left) / 2 + left;
        if (arr[middle] > key)
        {
            right = middle - 1;
            return BinarySearch(arr, left, right, key);
        }
        else if (arr[middle] < key)
        {
            left = middle + 1;
            return BinarySearch(arr, left, right, key);
        }
        else
            return middle;
    }
    return -1;
}

int RotateArray(int* arr, int _left,int _right, int key)
{
    int left = _left, right = _right, middle = (_left + _right) / 2 + left;
    if (arr[left] == arr[middle] && arr[middle] == arr[right])    //如果 arr[left] == arr[middle] && arr[right] == arr[middle] 此時不能確定左是單增還是右是單增     {
        Inorder(arr, left, right, key);
    }
    else if (arr[left] <= arr[middle])    //前半部分為單增區間
    {
        if (key >= arr[left] && key <= arr[middle]) //如果key落在了前半部分則使用折半查找法
        {
            return BinarySearch(arr, left, middle, key);
        }
        else
        {
            return RotateArray(arr, middle + 1, right, key);
        }
    }
    else    //后半部分為單增區間
    {
        if (key > arr[middle] && key <= arr[right])
        {
            return BinarySearch(arr, middle+1, right, key);
        }
        else
        {
            return RotateArray(arr, left, middle, key);
        }
    }
}

 

 

 

 

 

 

3.找出一個排序數組中的 K 出現的次數

解決思路:假設我們是統計數字k在排序數組中出現的次數,只要找出排序數組中第一個k與最后一個k的下標,就能夠計算出k的出現次數。
尋找第一個k時,利用二分查找的思想,我們總是拿k與數組的中間元素進行比較。如果中間元素比k大,那么第一個k只有可能出現在數組的前半段;如果中間元素等於k,我們就需要判斷k是否是前半段的第一個k,如果k前面的元素不等於k,那么說明這是第一個k;如果k前面的元素依舊是k,那么說明第一個k在數組的前半段中,我們要繼續遞歸查找。   同樣的思路,我們在數組中尋找最后一個k,如果中間元素比K大,那么k只能出現在數組的后半段;如果中間元素比K小,那么K只能出現在數組的前半段。如果中間元素等於k,而k后面的元素等於k,那么最后一個k只能在后半段出現;否則k為數組中最后的一個k。

 

/*排序數組中的K出現的次數*/
int GetFirstK(int* arr, size_t size, int value)
{
    assert(arr);
    int start = 0,middle, end = size - 1;
    while (start <= end)
    {
        middle = (end - start) / 2 + start;
        if (arr[middle]>value)
            end = middle - 1;
        else if (arr[middle] < value)
            start = middle + 1;
        else
        {
            if (middle - 1 >= 0 && arr[middle - 1] == value)
                end = middle - 1;
            else
                return middle;
        }
    }
    return -1;
}



int GetLastK(int* arr, size_t size, int value) { assert(arr); int start = 0, middle, end = size - 1; while (start <= end) { middle = (end - start) / 2 + start; if (arr[middle]>value) end = middle - 1; else if (arr[middle] < value) start = middle + 1; else { if (middle + 1 < size && arr[middle + 1] == value) start = middle + 1; else return middle; } } return -1; }

int GetNumberOfK(int* arr, int size, int value) { if (arr == NULL || size <= 0) return -1; int First = GetFirstK(arr, size, value); int Last = GetLastK(arr, size, value); if (First >= 0) // 說明value一定存在 return (Last - First + 1); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM