剑指offer(java实现)第6题“旋转数组的最小数字”-牛客网

题目描述

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

时间限制:3秒 空间限制:32768K 热度指数:347786

解答:

import java.util.ArrayList;
public class Solution {//思路:对一个n长度的非减排序数组进行旋转有两种情况:第一:旋转了1~n-1个数字,会形成两个非减排序的子数组,如: 4 5 和 1 2 3;它的最小值
    //是在第二个子数组的开头,同时,第一个子数组的所有元素都大于或者等于第二个子数组,可以利用二分查找法来处理;第二:旋转了0个数字,得到的旋转数组仍然是原数组:1 2 3 4 5,最小值就是第一个元素
//注意:第二种情况里面:当数组头节点=尾节点=中间节点的时候,无法用二分查找来缩小查找范围,如:0 1 1 1 1 1 ,旋转 0 1 1 1 1变成:1 0 1 1 1 1,,只能用顺序查找
    public int minNumberInRotateArray(int [] array) {
        if (null == array || array.length == 0) {
            return 0;
        }
        int n = array.length - 1;
        int first = 0;//二分查找的开头元素位置索引
        int min = first;//用一个新的元素记录最小值,是为了方便如果是第二种情况,就不需要循环直接返回首节点
        int last = n-1;//二分查找的末尾元素位置索引
        int middle = 0;//中间节点位置索引
        while (array[first] >= array[last]) {//当数组的开头节点大于等于数组的末尾节点时,需要进行循环判断
            if (last - first == 1) {//当二分查找的结束索引与开始索引之间相邻的时候,说明就找到了最小元素,
                //而且最小元素是结束索引上的元素(因为first指针总会指向第一个子数组,而第二个子数组总会指向第二个子数组)
                min = last;
                break;
            }
            middle = first + (last-first)/2;
            if (array[first] == array[middle] && array[middle] == array[last]) {//此时无法用二分查找
                // return 。。。
                //此处省略顺序查找的方法
            }
            if (array[middle] >= array[first]) {//当中间元素大于等于二分查找数组的开头元素时,说明中间元素落在了第一个子数组中,最小元素要去后面找
                first = middle;
            }else if (array[middle] <= array[last]) {//否则当中间元素小于等于二分查找数组的末尾元素时,说明中间元素落在了第二个子数组中,最小元素去前面找
                last = middle;
            }
        }
        //如果数组的第一个元素小于最后一个元素,说明:非减排序的数组的旋转数组是它本身:1 2 3 4 5,这时第一个元素就是最小元素
        return array[min];
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值