剑指Offer——旋转数组的最小数字(详细说明)

🐮客上剑指Offer题6,求解旋转数组的最小数字

题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

示例
[3,4,5,6,1,2]就是非递减排序数组[1,2,3,4,5,6]的一个旋转数组,输出的是旋转数组[3,4,5,6,1,2]中的最小值。

解题思路一:

看到求一个数组中的最小值,立马想到排序啊,然后输出第一个元素啊,so easy啊!给出思路一代码:

    public int minNumberInRotateArray1(int [] array) {
    	int len = array.length;
    	if(len == 0) {
    		return 0;
    	}
    	Arrays.sort(array);
    	return array[0];
    }

寥寥几行代码,完事!但是,《剑指Offer》上的题大多是练习算法的,因此为了提高算法的技能点,进一步进行解题,下面给出解题思路二。

解题思路二:

题中给出旋转数组是由一个非递减数组变化得到的,因此可知旋转数组是部分非递减有序的(旋转拼接点处为划分点,将旋转数组划分为两个有序数组),既然有序,还是查找,那当然是二分啦!
那怎么实现呢?
下面给出非递减有序数组旋转变化的情况示意图:
在这里插入图片描述
有序非递减数组的旋转数组的走向可以为图上三种情况,因此可以通过判断二分过程中的array[mid]与左右相邻的值的大小来判断mid是否为连接点,如果不是再与array[0]比较,判断连接点在哪。为什么通过与array[0]比较就可以判断呢?
因为原数组是非递减有序,因此旋转变换后,必有array[last]<=array[0],同时假设t是连接处,[0,t-1]是非递减,[t,last]是非递减,因此通过比较array[mid]和array[0]就可以判断连接点在哪个部分了。
代码如下:

    public int minNumberInRotateArray2(int [] array) {
        int len = array.length;
    	if(len == 0) {
    		return 0;
    	}
        
    	if(len == 1 || array[len-1] > array[0]) {//长度为1或者没有旋转
    		return array[0];
    	}
    	int low = 0;
    	int high = len-1;
    	while(low <= high) {
    		int mid = (low+high)/2;
    		if(array[mid] > array[mid+1]) {//凹部分,下降
    			return array[mid+1];
    		}
    		if(array[mid-1] > array[mid]) {//凸部分,上升
    			return array[mid];
    		}
    		if(array[mid] > array[0]) {//划分左右
    			low = mid+1;
    		}else {
    			high = mid-1;
    		}
    	}
    	return 0;
    }

好了,本人水平有限,如有错误和不足欢迎大家指正和指导!

我是菜鸡程序猿,菜鸡程序猿就是我!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值