题目:把一个数组最开始的若干元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

       如果单纯的从头到尾遍历数组一次,找出最小的元素,时间复杂度是O(n)。显然不是最优的解法。旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素大于或者等于后面子数组的元素,最小的元素刚好是这两个子数组的分界线。在排序的数组中可以用二分查找法实现O(logn)的查找。

      (a)把P1指向数组的第一个数字,P2指向数组的最后一个数字。由于P1和P2中间的数字5大于P1指向的数字,中间的数字在第一个子数组中,下一步把P1指向中间的数字。

      (b)P1和P2中间的数字1小于P2指向的数字,中间的数字在第二个子数组中。下一步把P2指向中间的数字。

      (c)P1和P2指向两个相邻的数字,则P2指向的是数组中最小的数字。

代码实现:

public class Solution{
     public static void main(String[] args){
           try{
                 int[] array={3,4,5,1,2};
                 int x=FindMin(array);
                 System.out.println(x);
           }catch(Exception e){
                 System.out.println(e.getMessage());
           }
     }

     public static int FindMin(int[] arr) throws Exception{
           if(arr==null||arr.length<=0){
                throw new Exception("Invalid parameters");
           }
           int head=0;
           int tail=arr.length-1;
           int min=Integer.MIN_VALUE;
           int mid;
           while(arr[head]>=arr[tail]){
                 if(tail-head==1){
                      min=arr[tail];
                      break;
                 }
                 mid=(head+tail)/2;
                 if(arr[mid]>arr[tail]){
                       head=mid;
                 }else{
                       tail=mid;
                 }
           }
           return min;
     }
}

       但是上述代码,并没有考虑到特殊情况,数组{1,0,1,1,1}和数组{1,1,1,0,1}都是递增排序数组{0,1,1,1,1}的旋转,最后执行的结果为1,并不是0。

      对于这种无法判断中间的数字是位于前面的子数组中还是后面的子数组中,无法缩小查找范围的情况,不得不采用顺序查找的方法特殊处理。

代码实现:

public class Solution{
     public static void main(String[] args){
           try{
               //特殊数组{1,1,1,0,1}和{1,0,1,1,1}
                int[] array={1,1,1,0,1}; 
                //int[] array={3,4,5,1,2};
                 int x=FindMin(array);
                 System.out.println(x);
           }catch(Exception e){
                 System.out.println(e.getMessage());
           }
     }

     public static int FindMin(int[] arr) throws Exception{
           if(arr==null||arr.length<=0){
                throw new Exception("Invalid parameters");
           }
           int head=0;
           int tail=arr.length-1;
           int min=Integer.MIN_VALUE;
           int mid;
           while(arr[head]>=arr[tail]){
                 if(tail-head==1){
                      min=arr[tail];
                      break;
                 }
                 mid=(head+tail)/2;
                 //如果下标为head,tail,mid的三个元素都相等,只能顺序查找
                 if(arr[head]==arr[tail]&&arr[mid]==arr[tail]){
                       return minInOrder(arr,head,tail);
                 }
                 if(arr[mid]>arr[tail]){
                       head=mid;
                 }else{
                       tail=mid;
                 }
           }
           return min;
     }

      public static int minInOrder(int[] arr,int head,int tail){
            int min=arr[head];
            for(int i=head+1;i<=tail;i++){
                if(min>arr[i]){
                     min=arr[i];
                }
            }
            return min;
      }
}

 

 posted on 2018-09-09 15:07  会飞的金鱼  阅读(100)  评论(0)    收藏  举报