问题描述:
如题,其中循环有序数组指的是对有序数组进行循环移位后的结果,如[7,8,9,0,1,2,3,4,5,6];
实现思路:
由循环有序数组结构可知,若数组不为整体有序,则最小值一定是处于无序子序列之中,如上述例子中,最小值一定处于7到1之间,而一定不处于1到6之间,根据该性质可以得到如下算法:
先进行判断该数组是否整体有序(arr[left] < arr[right]),若有序返回left即可。
对于整体无序情况(arr[left] < arr[right]),mid = left + (right - left) / 2,判断left - mid 和 mid - right是否为有序,
若arr[mid] > arr[right] 对mid - right部分进行查找,arr[mid] < arr[left] 对left - mid 部分进行查找.;
若以上条件均不满足即(arr[mid] <= arr[right] && arr[mid] >= arr[left]),又由于arr[left] >=arr[right] 所以可得:
arr[mid] = arr[left] = arr[right],对于该情况只能采用从头到尾的方式进行搜索了。
具体实现代码如下:
public static int selution(int[] arr) {
int left = 0, right = arr.length - 1, mid = 0;
while (right - left > 1) {
if (arr[left] < arr[right]) {
return left;
}
mid = left + (right - left) / 2;
// arr[left] >= arr[right]
if (arr[mid] < arr[left]) { //最小值在左端
right = mid;
}
if (arr[mid] > arr[right]) { //最小值在后面
left = mid;
}
if (arr[mid] >= arr[left] && arr[mid] <= arr[right]) {
//即 arr[right] = arr[left] = arr[mid]
return findMin(arr, left, right);
}
}
return arr[left] < arr[right] ? left : right;// 返回left right 中最小的
}
public static int findMin(int[] arr, int left, int right){
int minIndex = left ,min = arr[left];
for (int i = left + 1; i <= right; i++) {
if(arr[i] < min) {
min = arr[i];
minIndex = i;
}
}
return minIndex;
}