旋转数组的最小数字(Java)

题目:

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

第一思路:

刚拿到这道题我相信大多数人和我一样想到了时间复杂度为O(n)的查找算法,即遍历一遍数组找到自己满足题意的最小值元素。可以如果这样做,就违背了题意旋转数组,即没有利用旋转数组中的两部分有序原则。故需再思考。

最优思路:

(1)旋转数组实际上可以划分为两个排序的子数组,而且前面的子数组元素都大于或者等于后面的子数组的元素;(2)最小的元素刚好是这两个字数组的分界线;因为在排序的数组中我们可以用二分查找法实现O(logn)的查找。故旋转数组找最小元素值也可以采取二分查找的思路。

首先我们定义两个指针p1指向数组的第一个元素和p2指向数组的最后一个元素,接着我们找到中间的元素。如果该元素位于前面递增数组中,它应该大于或者等于第一个指针指向的元素,我们将p1指向中间元素;如果中间元素位于后面的递增数组中,那么它应该小于或者等于第二个指针指向的元素,我们把p2指向中间元素。不管移动p1还是p2,查找的范围都会缩小为原来一半,接下来利用更新后的两个指针重复上面的查找。按照上面的思路,p1始终在前面递增数组,p2始终在后面递增数组,最终p1会指向前面子数组的最后一个元素,第二个指针会指向后面子数组的第一个元素,即最小元素,结束循环。

有一特例是p1、p2和中间值都相等,这时候就老老实实循环遍历一次数组,找到最小值。

代码:

public class Main {

	//一般情况时的查找算法
	public int Min(int arrays[]){
		if(arrays == null){
			try {
				throw new Exception("Invalid parameters");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		int index1 = 0;
		int index2 = arrays.length - 1;
		int indexMid = index1;
		while(arrays[index1] > arrays[index2]){
			if(index2 - index1 == 1){ //如果差值为1,则index2下标的数一定是最小数
				indexMid = index2;
				break;
			}
			indexMid = ( index1 + index2 ) / 2; //取中间值
			if(arrays[index1] == arrays[index2] && arrays[indexMid] == arrays[index1]){ //特例
				return MinInOrder(arrays);
			}
			if(arrays[indexMid] >= arrays[index1]){ //如果中间值大于index1对应的值,则修改index1的值为中间值
				index1 = indexMid;
			}else if(arrays[indexMid] <= arrays[index2]){ //否则修改index2的值为中间值
				index2 = indexMid;
			}
		}
		return arrays[indexMid]; //indexMid对应的一定是最小值
	}
	//特例时的查找算法
	private int MinInOrder(int[] arrays) {
		int result = arrays[0];
		for (int i = 0; i < arrays.length; i++) {
			if(result > arrays[i]){
				result = arrays[i];
			}
		}
		return result;
	}
	//测试
	public static void main(String[] args) {
		int num1[] = {4, 5, 6, 7, 1, 2, 3};
		int num2[] = {1, 0, 1, 1, 1};
		int num3[] = {1, 1, 1, 0, 1};
		Main m1 = new Main();
		System.out.println(m1.Min(num3));
		System.out.println(m1.Min(num2));
		System.out.println(m1.Min(num1));
	}
}

小结:

这道题是二分查找的变形,考查二分查找。以及接收新事物的理解能力与转化能力。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值