旋转数组中的最小值

来源:互联网 发布:中文域名申请 编辑:程序博客网 时间:2024/05/29 09:20

问题

如果有一个序列,后一个元素大于等于前一个元素,然后旋转数组的元素,把前面的元素放到序列的后面;
例如原始数据为:
1,2,3,4,5,6
其中的一个选装为:
3,4,5,6,1,2
然后求旋转后的数组中的最小值
思路:其实最简单的就是遍历一遍数组,冒泡一下,其时间复杂度为O(n);有没有什么可以改进一下那,要充分利用已知条件,旋转后的数组可以化为两个有序的子数组,对于有序的数组可以采用二分法查找;
如果中间的元素大于等于前面的元素,那么中间的元素属于第一个递增的字数组内;然后首指针指向中间元素,缩小搜索范围;
如果中间的元素小于等于后面的元素,那么中间的元素是属于第二个递增的字数组内;然后尾指针指向中间元素,缩小搜索范围;
这样保证首指针和尾指针分别在两个字数组内,当两个指针相邻时,尾指针指向的就是旋转后的最小值。可以改善O(n)的时间复杂度,本算法时间复杂度为O(logn).

代码

package edu.liangman.offer;/** * Created by lm on 2017/1/3. * 旋转数组中的最小值 */public class MinRotatingarray {    /**     *     * @param arr  遍历的数组     * @param begin 数组的开始下标     * @param end 结束下标     * @return     */    public int getMinEle(int[] arr,int begin,int end) throws Exception {        int result = 0;        int mid = 0;        if(arr==null)        {            throw new Exception("数组为空");        }        /*         如果第一个元素是最小值,直接返回;也就是旋转了0个元素,即数组没有选装        * */        result = begin;         while(arr[begin]>=arr[end]){            if(end-begin==1){ //后面-前面的                result=end;                break;            }            mid = (end+begin)/2; // +            if(arr[mid]==arr[begin]&&arr[mid]==arr[end]) {                return  squenSearch(arr,begin,end);            }            if(arr[mid]>=arr[begin]){                begin = mid;            }            if(arr[mid]<=arr[end]){                end = mid;            }        }        return arr[result];    }    public int squenSearch(int[] arr,int begin,int end){        int min = arr[begin];        for (int i =1;i<arr.length;i++){            if(arr[i]<min)                min = arr[i];        }        return min;    }    public static void main(String[] args) throws Exception {        MinRotatingarray mra = new MinRotatingarray();        //int[] arr = {3,4,5,1,2};        int[] arr = {1,0,1,1,1}; //源数组为0,1,1,1,1        int retvalue =mra.getMinEle(arr,0,arr.length-1);        System.out.print(retvalue);    }}

运行结果

这里写图片描述

0 0