1. 程式人生 > >劍指offer--旋轉陣列的最小值

劍指offer--旋轉陣列的最小值

題目如下

把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。 輸入一個非減排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。 例如陣列{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該陣列的最小值為1。 NOTE:給出的所有元素都大於0,若陣列大小為0,請返回0。

解題思路:
有三種思路

  1. 很簡單了,遍歷陣列取得最小值。
    我最開始就是這種想法。。。太low了
    function minNumberInRotateArray(rotateArray)
    {
        if( rotateArray.length === 0 ){
            return 0;
        }else{
            let len = rotateArray.length;
            let min = rotateArray[0];
            for(var i = 1 ; i < len ; i++){
                if( rotateArray[i] < min ){
                    min = rotateArray[i];
                }
            }
            return min;
        }
    }
    

  1. 對上面的方法進行部分優化,可以將陣列看出兩個非遞減的陣列,a[x1…xn] b[y1…yn]
    顯然最小值就是y1,在a中x1到xn是非遞減的,所以遍歷時,找到第一個a[n] > a[n+1]的n即可,結果就是a[n+1]
    同時對於[1,1,1,1]這種恆等的陣列需要做特殊處理
    function minNumberInRotateArray2(rotateArray)
    {
        if( rotateArray.length === 0 ){
            return 0;
        }else{
            let len = rotateArray.length;        
            for(var i = 1 ; i < ( len - 1 ) ; i++){
                if( rotateArray[i] > rotateArray[ i + 1] ){
                    return rotateArray[i+1]
                }
                if( i ===  len - 1){
                    return rotateArray[i];
                }
            }        
        }
    }
    

  1. 這個是比較高階的一種方法了,就是利用二分法進行查詢
    同上面的方法,將陣列arr看作兩個非遞減的陣列a[x1…xn] , b[y1…yn]
    3-1. 取left = 0, right =arr.length -1;
    3-2. 取left和right的中間值 mid
    3-3. 拿mid的對應的值與left對應的值進行比較
    如果arr[mid] >= arr[left],說明mid位於a[x1…xn]中,最小值b[y1]位於mid和right中,設定left=mid
    如果arr[mid] < arr[left],說明mid位於b[y1…yn]中,最小值b[y1]位於left和mid中,設定right=mid
    3-4. 重複上述步驟3-2和3-3直到 right - left == 1
    3-5. 結果arr[left] = a[xn], arr[right] = b[y1],最小值為arr[right]
    function minNumberInRotateArray(rotateArray)
    {
        if( rotateArray.length === 0 ){
            return 0;
        }if( rotateArray.length === 1){
            return rotateArray[0];
        }else{
            let len = rotateArray.length;        
            let left = 0;
            let right = len - 1;
            while( right - left !== 1 ){
                let center =  Math.floor( (left + right) / 2 );            
                if(  rotateArray[center] >= rotateArray[left]){
                    left = center;
                }else{
                    right = center;
                }
            }
            return rotateArray[right];
        }
    }