旋转数组的最小数字

剑指Offer

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

思路:

按上述题意描述一般情况输入的数组可以分为两个递增序列(相等也算),如果使用直接查找遍历 那么时间复杂度是 O(N),这样虽然可以但是题目就没意思了。数组中的第一个元素大于或等于最后一个元素,使用二分法,一个指标指向数组的头 start,一个指向数组的末端 end,middle=(start+end)/2,若 middle 下标对应的值大于等于 start 下标对应的值,middle 属于第一个序列 start = middle ,若 middle 下标对应的值小于 end 则属于第二个序列,end = middle。 到最后 end 与 middle 相差为1时 最小值在 end下标上。

特殊情况:1,0,1,1,1,1,1 当 start = middle = end 相等时,就无法使用二分查找,只能遍历所有。

import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
    if(array.length==0)
        return 0;
    //数组长度为 1
    if(array.length==1){
        return array[0];
    }
    //数组有序
    if(array[0] < array[array.length-1]){
        return array[0];
    }
    
    int start=0,end=array.length-1;
    int middle=start;
   
    while(true){
        if(end-middle==1){
            break;
        }
        middle=(start+end)/2;
        //遍历所有
        if(array[start]==array[middle] && array[middle]==array[end]){
             return findMin(array,start,end);
        }
        
        if(array[start]<=array[middle]){
            start=middle;
        }else if(array[middle]<=array[end]){
            end=middle;
        } 
    }
    return array[end];
}

public int findMin(int [] array,int start,int end){
    int min=array[start];
    for(int i=start+1;i<=end;i++){
        if(array[i]<min){
            min=array[i];
        }
    }
    return min;
}

}
posted @ 2018-07-16 11:28  罗贱人  阅读(144)  评论(0编辑  收藏  举报