劍指OFFER之旋轉數組的最小數字(九度OJ1386)


題目描述:

把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該數組的最小值為1。 

輸入:

輸入可能包含多個測試樣例,對於每個測試案例,

輸入的第一行為一個整數n(1<= n<=1000000):代表旋轉數組的元素個數。

輸入的第二行包括n個整數,其中每個整數a的范圍是(1<=a<=10000000)。

輸出:

對應每個測試案例,

輸出旋轉數組中最小的元素。 

樣例輸入:

5
3 4 5 1 2

樣例輸出:

1 

解題思路:

  首先注意題目的要求,是遞增數組的旋轉數組。這怎么理解呢?

  比如,數組1 2 3 4 5,經過旋轉可以旋轉成為 2 3 4 5 1,或者 3 4 5 1 2 或者 1 2 3 4 5 或者 5 1 2 3 4等等。

  說的更復雜點,這其中的數字可以重復,那么數組 0 0 1 1 1 1 就可以旋轉成為 1 1 1 0 0 1或者 1 1 1 1 0 0 等等,考慮到這些復雜的情況,那么就好處理了。

  這里最簡單,也是鑽空子的一種方式,就是在你輸入數據的時候,直接檢查,找出最小值。這種情況也是可以AC的。

  正常的解題思路,我們不能挨個遍歷,這就顯得不夠高大上了,二典型的縮小時間復雜度的方法,就是二分查找了。但是考慮到一種特殊的情況,比如1 0 1 1 1是 0 1 1 1 1的旋轉數組,此時進行二分,頭尾中間都是1,這怎么判斷呢?那么我們就兩遍都進行一次查找,最后的結果進行一次比較就可以了。這樣明顯可以縮小時間復雜度。

鑽空子的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int arr[1000000];
int main(void){
    int i,n;
    while(scanf("%d",&n)!=EOF && n>=1 && n <= 1000000){
        memset(&arr,0,sizeof(int)*1000000);
        int smallest = 10000001;
        for(i=0;i<n;i++){
            scanf("%d",&arr[i]);
            if(smallest > arr[i])
                smallest = arr[i];
        }
        printf("%d\n",smallest);
    }
    return 0;
}
/**************************************************************
    Problem: 1386
    User: xhalo
    Language: C
    Result: Accepted
    Time:1000 ms
    Memory:4820 kb
****************************************************************/

正常的解題思路:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int arr[1000000];
int binarySearch(int *arr,int front,int rear);
int main(void){
    int i,n;
    while(scanf("%d",&n)!=EOF && n>=1 && n <= 1000000){
        memset(&arr,0,sizeof(int)*1000000);
        int smallest = 10000001;
        for(i=0;i<n;i++){
            scanf("%d",&arr[i]);
        }
        printf("%d\n",binarySearch(arr,0,n-1));
    }
    return 0;
}
int binarySearch(int *arr,int front,int rear){
    if(front+1 == rear || front == rear)
        return arr[rear]<arr[front]?arr[rear]:arr[front];
    int index = (front+rear)/2;
    if(arr[front] == arr[index] && arr[rear] == arr[index]){//此時兩邊中間都一樣,考慮到特殊情況,我們兩遍均遍歷一次,進行最后的比較大小。
        int find1 = binarySearch(arr,front,index);
        int find2 = binarySearch(arr,index+1,rear);
        return find1<find2?find1:find2;
    }else if(arr[index] >= arr[front] && arr[index] > arr[rear])
        binarySearch(arr,index,rear);
    else
        binarySearch(arr,front,index);
}
/**************************************************************
    Problem: 1386
    User: xhalo
    Language: C
    Result: Accepted
    Time:990 ms
    Memory:4820 kb
****************************************************************/

 

 
         


免責聲明!

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



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