1. 程式人生 > >lintcode尋找旋轉排序陣列中的最小值/迴圈有序陣列的查詢

lintcode尋找旋轉排序陣列中的最小值/迴圈有序陣列的查詢

問題描述

迴圈有序陣列

假設一個旋轉排序的陣列其起始位置是未知的(比如0 1 2 4 5 6 7 可能變成是4 5 6 7 0 1 2)。

你需要找到其中最小的元素。

你可以假設陣列中不存在重複的元素。

筆記

還是要用二分查詢。再加一點細節處理。參考《劍指offer》

我們用兩個指標分別指向陣列的第一個元素和最後一個元素。按照題目中旋轉的規則,第一個元素應該是大於或者等於最後一個元素的(這其實不完全對,還有特例,後面再加以討論)

接著我們可以找到陣列中間的元素。如果該中間元素位於前面的遞增子陣列,那麼它應該大於或者等於第一個指標指向的元素。此時陣列中最小的元素應該位於該中間元素的後面。我們可以把第一個指標指向該中間元素,這樣可以縮小尋找的範圍。移動之後的第一個指標仍然位於前面的遞增子陣列之中。

同樣,如果中間元素位於後面的遞增子陣列,那麼它應該小於或者等於第二個指標指向的元素。我們可以把第二個指標指向該中間元素。這樣也可以縮小尋找的範圍。移動之後的第二個指標仍然位於後面的遞增子陣列之中。

不管是移動第一個指標還是第二個指標,查詢範圍都會縮小到原來的一半。接下來我們再用更新之後的兩個指標,重複做新一輪的查詢。

程式碼

class Solution {
public:
    /**
     * @param num: a rotated sorted array
     * @return: the minimum number in the array
     */
int findMin(vector<int> &num) { // write your code here int start = 0; int end = num.size() - 1; int res = 0; while (num[start] >= num[end]) { if (start == end - 1) { res = end; break
; } int mid = (start + end) / 2; if (num[start] == num[mid] && num[mid] == num[end]) { int tmp = num[start]; for (int i = start + 1; i <= end; i++) { if (num[i] < tmp) return num[i]; } } if (num[mid] >= num[start]) start = mid; if (num[mid] <= num[end]) end = mid; } return num[res]; } };

相關題目

在迴圈有序陣列中尋找某個數

程式碼

//
//  main.cpp
//  rotate_array
//
//  Created by SteveWong on 26/09/2016.
//  Copyright © 2016 SteveWong. All rights reserved.
//

#include <iostream>
#include <vector>
using namespace std;

int binsearch(vector<int> a, int tar, int lo, int hi)
{
    while (lo <= hi)
    {
        int mid = (lo + hi) / 2;
        if (a[mid] == tar)
        {
            return mid;
        }
        else if (a[mid] < tar)
        {
            lo = mid + 1;
        }
        else
        {
            hi = mid - 1;
        }
    }
    return -1;
}

int find(vector<int> a, int tar, int lo, int hi)
{
    while (a[lo] > a[hi])
    {
        int mid = (lo + hi) / 2;
        if (a[mid] == tar)
            return mid;
        if (a[lo] < a[mid])//前一半是正常有序,後一半是迴圈有序
        {
            if (a[lo] <= tar && tar < a[mid])//目標在前一半,可以直接二分
            {
                return binsearch(a, tar, lo, mid-1);
            }
            else//在後一半迴圈有序陣列中查詢
            {
                lo = mid + 1;
            }
        }
        else if (a[mid] < a[hi])//後一半正常有序,前一半迴圈有序
        {
            if (a[mid] < tar && tar <= a[hi])
            {
                return binsearch(a, tar, mid+1, hi);
            }
            else
            {
                hi = mid - 1;
            }
        }
    }
    //跳出迴圈,代表a[lo] < a[hi]
    return binsearch(a, tar, lo, hi);
}

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    vector<int> a = {4, 5, 6, 7, 1, 2, 3};
//    int tar = 2;
    cout << find(a, 2, 0, 6) << endl;
    cout << find(a, 3, 0, 6) << endl;
    cout << find(a, 4, 0, 6) << endl;
    cout << find(a, 5, 0, 6) << endl;
    cout << find(a, 6, 0, 6) << endl;
    cout << find(a, 7, 0, 6) << endl;
    cout << find(a, 1, 0, 6) << endl;
    cout << find(a, -8, 0, 6) << endl;
    cout << find(a, 9, 0, 6) << endl;

    return 0;
}