剑指offer:旋转数组的最小数字

Posted huanglf714

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer:旋转数组的最小数字相关的知识,希望对你有一定的参考价值。

题目

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

解题思路

这是一道二分查找的变形题,这里的旋转数组是两个有序的递增子数组拼接起来的,且前面一个子数组里的任意一个数都大于后面子数组中的数。而要找的最小值就是前后两个子数组的分界点。

 

用三个指针begin、end、middle分别指向数组的首尾和中间元素

1)若middle元素大于或者等于begin元素说明中间元素位于前半部分数组中,最小元素在后半部分的数组中,则将begin设为middle继续在后半部分中寻找

2)若middle元素小于或者等于end元素说明中间元素位于后半部分数组中,最小部分在前半部分或者中间元素就是最小元素,则将end设为middle继续在前半部分中寻找

这样不断缩小范围,直到最后begin和end会成为相邻的元素,此时end所指元素就是最小值

 

特殊情况:

1)0个元素旋转到后半部分,那么此时旋转数组就是一个非递减数组,最小值就是第一个元素,也就是为什么初始middle设为0的原因

2)当begin、end、middle三个元素都相等时,无法判断中间元素在前半部分数组还是后半部分数组,只能遍历数组寻找最小值

例如1,1,1,0,1和1,0,1,1,1都可以看成是0,1,1,1,1的翻转数组

 

代码

 1     public int minNumberInRotateArray(int [] array) 
 2         if(array.length==0)
 3             return 0;
 4         int begin = 0,end = array.length-1,middle = 0;
 5         while(array[begin]>=array[end])
 6             if((end-begin)==1)
 7                 middle = end;
 8                 break;
 9             
10             middle = (begin+end)/2;
11             if(array[begin]==array[middle]&&array[middle]==array[end])
12                 return minInOrder(array,begin,end);
13             
14             if(array[middle]>=array[begin])
15                 begin = middle;
16             else if(array[middle]<=array[end])
17                 end = middle;
18             
19             
20         
21         return array[middle];
22     
23     
24     private int minInOrder(int[] array,int begin,int end)
25         int min = array[begin];
26         for(int i = begin+1;i<end;i++)
27             if(min>array[i])
28                 min = array[i];
29             
30         
31         return min;
32     

 

以上是关于剑指offer:旋转数组的最小数字的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer 11. 旋转数组的最小数字 的详细题解

剑指Offer:旋转数组的最小数字11

剑指offer---旋转数组的最小数字

旋转数组的最小数字-剑指Offer

剑指 Offer 11. 旋转数组的最小数字暴力二分查找

剑指offer 6.旋转数组的最小数字