剑指Offer_08 旋转数组的最小数字

原创 2016年08月29日 20:54:27

参考:http://blog.csdn.net/jsqfengbao/article/details/47121489

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为旋转。 输入一个递增的排序的数组的一个旋转,输出旋转数组的最小元素。
    思路:我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都是大于或者等于后面子数组的元素。我们还注意到最小的元素刚好是这两个子数组的分界线。在排序的数组中我们可以利用二分查找来实现O(logn)的查找。本题给出的数组在一定程度上是排序的,因此我们可以试着用二分查找的思路来寻找这个最小的元素。但是如果数组中三个节点位置数字都相同,则使用二分查找不能排除,只能用顺序查找方法(1111101)。

这里写图片描述

我们先把第一个指针指向第0个元素,把第二个指针指向第4个元素,如图所示。位于两个指针中间(在数组的下标是2)的数字是5,它大于第一个指针指向的数字。因此中间数字5一定位于第一个递增字数组中,并且最小的数字一定位于它的后面。因此我们可以移动第一个指针让它指向数组的中间。
此时位于这两个指针中间的数字为1,它小于第二个指针指向的数字。因此这个中间数字为1一定位于第二个递增子数组中,并且最小的数字一定位于它的前面或者它自己就是最小的数字。因此我们可以移动第二个指针指向两个指针中间的元素即下标为3的元素。
此时两个指针的距离为1,表明第一个指针已经指向了第一个递增子数组的末尾,而第二个指针指向第二个递增子数组的开头。第二个子数组的第一个数字就是最小的数字,因此第二个指针指向的数字就是我们查找的结果。

上述方法是否就一定够完美了呢?面试官会告诉你其实不然。他将提示我们再仔细分析小标leftIndex和rightIndex分别和途中P1和P2相对应)的两个数相同的情况。在前面,当着两个数相同,并且它们中间的数相同的也相同时,我们把IndexMid赋给了leftIndex,也就是认为此时最小的数字位于中间数字的后面。是不是一定一样?
我们再来看一个例子。数组{1,0,1,1,1}和数组{1,1,1,0,1}都可以堪称递增排序数组{0,1,1,1,1}的旋转,图2分别画出它们由最小数字分隔开的两个子数组。
这里写图片描述
这两种情况中,第一个指针和第二个指针指向的数字都是1,并且两个指针中间的数字也是1,这3个数字相同。在第一种情况中,中间数字(下标为2)位于后面是子数组;在第二种情况中,中间数字(下标为2)位于前面的子数组中。因此,当两个指针指向的数字及它们中间的数字三者相同的时候,我们无法判断中间的数字是位于前面的子数组中还是后面的子数组中国,也无法移动两个指针来缩小查找的范围。此时,我们不得不采用顺序查找的方法。

代码:
public class E08MinNumberInRotatedArray {  
    public int minInReversingList(int[] arr){  
        if(arr==null){  
            return -1;  
        }  
        int leftIndex = 0;  
        int rightIndex = arr.length -1;  
        int midIndex = leftIndex;  
        while(arr[leftIndex]>= arr[rightIndex]){  
            if(rightIndex - leftIndex <= 1){  
                midIndex = rightIndex;  
                break;  
            }  
            midIndex = (leftIndex+rightIndex)/2;  
            if(arr[leftIndex]== arr[rightIndex] && arr[midIndex]== arr[leftIndex]){  
                return MinInOrder(arr,leftIndex,rightIndex);  
            }  
            if(arr[midIndex] >= arr[leftIndex]){  
                leftIndex = midIndex;  
            }else if(arr[midIndex] < arr[rightIndex]){  
                rightIndex = midIndex;  
            }  
        }  
        return arr[midIndex];  
    }  
    public int MinInOrder(int[] arr,int leftIndex,int rightIndex){  
        int result = arr[leftIndex];  
        for(int i = leftIndex +1;i<rightIndex;i++){  
            if(result> arr[i]){  
                result = arr[i];  
            }  
        }  
        return result;  
    }  
    public static void main(String[] args){  
        E08MinNumberInRotatedArray test = new E08MinNumberInRotatedArray();  
        int[] arr={3,4,5,1,2};    //{2,2,2,2,2,0,1,2,2};  
        System.out.println(test.minInReversingList(arr));  

    }  
}  
版权声明:本文为博主原创文章,未经博主允许不得转载。

面试题08_旋转数组的最小数字——剑指offer系列

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

剑指Offer_面试题08_旋转数组的最小数字

思路: 如序列 3,4,5,1,2   观察到数组旋转后可以分为两个部分,两个排序的子数组,而且前面的元素都不小于后面数组的元素。而且最小值元素刚好是这两个数组的分界线。 在有序数组中可以使用二分查...

【剑指Offer学习】【面试题8 : 旋转数组的最小数字】

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

剑指offer面试题八:旋转数组的最小数字

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

【剑指offer】面试题8:旋转数组中的最小数字

//旋转数组中的最小数字 //题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转,输入一个递增排序的数组,数组旋转数组的最小元素。 //遍历数组一次,找出最小,效率为O(n),显然...

leetcode之Search in Rotated Sorted Array,剑指offer之旋转数组的最小数字

输入一个递增数组的旋转,

《剑指offer》:[11]旋转数组的最小数字

题目:把一个数组最开始的若干元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小的元素。   例如:数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋...
  • gogoky
  • gogoky
  • 2016年06月03日 15:29
  • 285

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

1. 问题描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,...

旋转数组的最小数字(剑指offer)

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

JAVA实现旋转数组的最小数字问题(《剑指offer》)

题目:旋转数组的最小数字 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减序列的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:剑指Offer_08 旋转数组的最小数字
举报原因:
原因补充:

(最多只允许输入30个字)