剑指offer编程题Java实现——面试题8旋转数组的最小数字

 剑指offer面试题8:旋转数组的最小数字
 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序数组的一个旋转,输出旋转数组的最小元素。
 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1
旋转数组的特点: 1,旋转之后的数组可以分为两个排序的子数组,且前面的子数组的元素都大于或等于后面子数组的元素。 2,最小或者最大元素位于两个子数组的分界
解题思路:在排序数组中,可以使用二分查找法进行查找 利用左右两个指针和中间指针元素大小关系判断中间元素是位于前面的子数组还是后面的子数组,缩小查找范围 需要考虑的特例: 1,排序数组本身仍是该数组的一个旋转 2,如果数组内有重复元素,那么有可能出现左右两指针元素与中间元素相同,无法判断中间元素属于前面子数组还是后面子数组,此时用顺序查找
 1 package Solution;
 2 
 3 /**
 4  * 剑指offer面试题8:旋转数组的最小数字
 5  * 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序数组的一个旋转,输出旋转数组的最小元素。
 6  * 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1
 7  * 旋转数组的特点:
 8  *         1,旋转之后的数组可以分为两个排序的子数组,且前面的子数组的元素都大于或等于后面子数组的元素。
 9  *         2,最小或者最大元素位于两个子数组的分界
10  * 解题思路:在排序数组中,可以使用二分查找法进行查找
11  * 利用左右两个指针和中间指针元素大小关系判断中间元素是位于前面的子数组还是后面的子数组,缩小查找范围
12  * 需要考虑的特例:
13  *         1,排序数组本身仍是该数组的一个旋转
14  *         2,如果数组内有重复元素,那么有可能出现左右两指针元素与中间元素相同,无法判断中间元素属于前面子数组还是后面子数组,此时用顺序查找
15  * @author GL
16  *
17  */
18 public class No8FindMinInRotatedSortedArray {
19 
20     public static void main(String[] args) {
21         int[] array1={3,4,5,1,2};
22         System.out.println("升序排序数组的一个旋转数组,无重复数字:"+findMin(array1));
23         int[] array2={1,2,3,4,5};
24         System.out.println("升序排序数组:"+findMin(array2));
25         int[] array3={1};
26         System.out.println("只包含一个数字的数组:"+findMin(array3));
27         int[] array4={2,4,2,2,2,2,2};
28         System.out.println("包含重复元素的数组:"+findMin(array4));
29         int[] array5=null;
30         System.out.println("null数组:"+findMin(array5));
31 
32     }
33     
34     public static int findMin(int[] array){
35         if(array==null||array.length<=0)
36             throw new RuntimeException("invalid array");
37         int indexLow=0;
38         int indexHigh=array.length-1;
39         //旋转数组为排序数组本身的特例
40         int indexMiddle=indexLow;
41         while(array[indexLow]>=array[indexHigh]){
42             if(indexHigh-indexLow==1){
43                 indexMiddle=indexHigh;
44                 break;
45             }
46             //考虑两侧数字和中间数字相同的特殊情况,采用顺序查找算法查找最小值
47             indexMiddle=(indexLow+indexHigh)/2;
48             if(array[indexMiddle]==array[indexLow]&&array[indexHigh]==array[indexLow])
49                 return findMinInOrder(array,indexLow,indexHigh);
50             if(array[indexMiddle]>=array[indexLow])
51                 indexLow=indexMiddle;
52             else
53                 indexHigh=indexMiddle;
54         }
55         return array[indexMiddle];
56     }
57     //顺序查找
58     private static int findMinInOrder(int[] array,int indexLow,int indexHigh){
59         int result=array[indexLow];
60         for(int i=indexLow+1;i<indexHigh;i++){
61             if(array[i]<result)
62                 result=array[i];
63         }
64         return result;
65     }
66 }

 

posted @ 2017-02-26 18:58  知其然,后知其所以然  阅读(1153)  评论(0编辑  收藏  举报