旋转数组中的最小值

问题

如果有一个序列,后一个元素大于等于前一个元素,然后旋转数组的元素,把前面的元素放到序列的后面;
例如原始数据为:
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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值