剑指Offer——11.旋转数组的最小数字

题目:

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

算法思想:

本题给出的数组在一定程度上是排序的,因此可以用二分查找的思想来解决问题。

1.定义两个指针分别指向数组的第一个元素和最后一个元素。根据旋转的规则,得知第一个元素应该大于或者等于最后一个元素。

2.找到中间元素,如果比左指针元素大,那么最小元素在右边,将左指针移到中间,继续查找;如果比左指针元素小,那么最小元素在左边(含该元素),将右指针移到中间,继续查找;

3.直到两个指针临近,左指针位于前面递增子数组的最后一个元素,指向最大元素;右指针位于后面递增子数组的第一个元素,指向最小元素。

(特例,如果左、右指针指向的元素与中间元素的值都相同,只能按顺序查找)

代码实现:

	public int rotateArrMin(int[] arr) {
		if(arr == null || arr.length <= 0)	//非空判断
			throw new RuntimeException("Invalid Input");
		
		//定义左、右指针
		int left = 0;
		int right = arr.length-1;
		int middle;
		
		while(left < right) {
			if(right - left == 1)	//两个指针临近,找到最小元素
				return arr[right];
			
			middle = (left + right)/2;	//确定中间位置
			if(arr[left] == arr[middle] && arr[right] == arr[middle])	//左、中、右三值相同时,顺序查找
				return minInorder(arr,left,right);
			else if(arr[middle] >= arr[left])	//中间元素大于等于左指针元素,左指针移到中间
				left = middle;
			else 								//否则,右指针移到中间
				right = middle;
		}
		return 0;
	}
	
	private int minInorder(int[] arr, int left, int right) {
		int min = arr[left];
		for(int i = left +1; i <= right; i++) {
			if(min > arr[i])
				min = arr[i];
		}
		return min;
	}

猜你喜欢

转载自blog.csdn.net/BlackMaBa/article/details/81564840