旋转数组 将一个有序数组前一部分移到后端 例如 12345---34512
1.求旋转数组的最小值
数组基本有序可以考虑二分查找来解决,考虑旋转数组的特点前半部分递增后半部分递减,使用两个指针,第一个index1指向递增部分,第二个index2指向递减部分,不断逼近,当两者距离之差index2-index1等于1,可以得到最小值为第二个指针index2位置的数值。
求出中点值 mid
四种情况,
1.index2-index1==1 此时最小值即为arr[index2].
2.mid在前半部分 3,4,5,6,7,8,9,0,1,2 判断特征为 arr[mid]>arr[index1] && arr[mid]>arr[index2],此时最小值肯定在mid右边 即index1=mid;
3.mid在后半部分 7,8,9,0,1,2,3,4,5,6 判断特征为 arr[mid]<arr[index1] && arr[mid]<arr[index2]此时最小值在mid左边 index2=mid;
4.如果arr[index1]==arr[mid]==arr[index2] 此时无法判断最小值在mid两边位置,只能遍历查找最小值。
public static int minNum(int[] arr){
int index1 = 0;
int index2 = arr.length-1;
int min = arr[index2];
while(index1 < index2){
System.out.println(index1 + " " + index2);
if(index2 - index1==1){
min = arr[index2];
break;
}
int mid = (index1 + index2) >> 1;
if(arr[mid]>arr[index1] && arr[mid]>arr[index2])
index1 = mid;
else if(arr[mid]<arr[index1] && arr[mid]<arr[index2])
index2 = mid;
else{
for(int i=index1; i<index2; i++){
if(arr[i]<min)
min = arr[i];
}
}
}
return min;
}
2.旋转数组查找某一个数字
数组基本有序,考虑二分查找 lo hi mid指针
1.如果arr[mid]==num 直接返回mid
2. mid值在前半部分 如 3,4,5,6,7,8,9,0,1,2 判断特征: arr[mid]>arr[lo] && arr[mid]>arr[hi]
比较arr[mid]与num关系:
在mid左边 arr[lo]<=num<arr[mid](注意等号取值,否则端点处值查找不到) mid左边此时完全有序,可以利用二分查找
在mid右边 mid右边数组为先增后减,即为一个旋转数组的查找的递归问题
3. mid值在后半部分 如7,8,9,0,1,2,3,4,5,6 判断特征 arr[mid]<arr[lo] && arr[mid]<arr[hi]
比较arr[mid]与num关系:
在mid右边 arr[mid]<num<=arr[hi ]mid右边数组为完全有序,二分查找
在mid左边 mid左边数组也是一个旋转数组 原来问题的递归问题
public static int findNum(int[] arr, int num, int lo, int hi){
int mid = (lo + hi) >> 1;
if(arr[mid]==num)
return mid;
else if(arr[mid]>arr[lo] && arr[mid]>arr[hi]){
// arr[lo]<=num num<=arr[hi] 取值等号为了处理边界情况,确定目标值所在范围然后执行二分查找
if(arr[lo]<=num && num<arr[mid])
return binaryFind(arr, num, lo, mid);
else
return findNum(arr, num, mid, hi);
}else{
if(arr[mid]<num && num<=arr[hi])
return binaryFind(arr, num, mid, hi);
else
return findNum(arr, num, lo, mid);
}
}
public static int binaryFind(int[] arr, int num, int lo, int hi){
while(lo<=hi){
int mid = (lo+hi)>>1;
if(arr[mid]==num)
return mid;
else if(arr[mid]<num)
lo = mid + 1;
else
hi = mid - 1;
}
return -1;
}
对于旋转数组基本有序,查找时可以考虑二分查找。由于数组特点是先增后减,前半部分与后半部分长度未定,因此首先需要判断mid中点值的位置,在前半部分还是后半部分,根据中点值可以将原数组划分为 一个旋转数组以及一个完全有序的数字,因此可以递归来解决问题。