声明: 本总结仅为个人学习总结,以防止遗忘而作,不得转载和商用。
问题描述
假定一个排序数组(已经有序) 以某个未知元素为支点做了旋转,如:原数组 0124567 旋转后得到 4567012 。请找出旋转后数组的最小值。假定数组中没有重复数字。
显然把数组遍历一遍就能找到最小值,但是时间复杂度达到 O(n) 。有没有更快的解决办法?
问题分析
旋转之后的数组实际上可以划分成两个有序的子数组:前面子数组的大小都大于后面子数组中的元素;
用索引 left,right 分别指向首尾元素,元素不重复。
若子数组是普通升序数组,则 A[left]<A[right]。
若子数组是循环升序数组(可以理解为两不同的递增序列),前半段子数组的元素全都大于后半段子数组中的元素:A[left]>A[right],计算中间位置 mid=(low+high)/2;
显然, A[low…mid] 与 A[mid+1…high] 必有一个是循环升序数组,一个是普通升序数组。
若:A[mid]>A[high],说明子数组 A[mid+1,mid+2,…high] 循环升序;更新 low=mid+1;
若:A[mid]<A[high] ,说明子数组 A[mid+1,mid+2,…high] 普通升序;更新:high=mid。
Java代码实现:
public static int findMin(int a[]) {
int low = 0;
int high = a.length-1;
int mid;
while (low<high) {
mid = (low + high) / 2;
if (a[mid] < a[high]) {
high = mid;//最小值在左半部分
}else {
low = mid + 1;//最小值在右半部分
}
}
return a[low];
}
测试代码:
public static void main(String[] args) {
int a[] = {6,7,0,1,2,3,4,5};
System.out.println(findMin(a));
}
输出结果: 0
不管0在前半段还是后半段,总能正确输出结果
网友评论