1.首先这题给出的数组原来是一个递增数组,出题人很明显希望我们用上这个条件,那么递增数组的旋转有什么特性呢?
2.不难发现,如果是一个正常的递增数组,数组最小的元素是第一个元素,数组最大的元素就是最后一个元素;当你把他旋转后,最大的元素就会在最小的数组元素的前面,以这两个元素(设为left和right)为边界,这个数组实际上是由两个递增数组组成;对于这种情况,剑指offer给的思路是二分查找,用两个指针分别指向数组开头和数组结尾,判断中间元素处于第一个数组还是处于第二个数组,中间元素比左边的元素大,说明处在第一个递增数组,那么middle及其右边的元素可能更大,left=middle;如果中间元素比右边的元素小,说明处在右边的递增数组,那么middle及其左边的元素可能更小,right = middle(这样就缩小了右边界);当left和right处在相邻的位置上时,ok,left指向数组最大,right指向数组最小;
3.正常的数组说完了,不好意思总有不正常情况,首先正常情况肯定是left指向的元素大于等于right指向的元素的,不然呢?;
然后如果left,right,middle三个数相等,你是无法判断属于前一个数组还是后一个数组的,老实点顺序查找;
java实现:
public class Solution {
public int minNumberInRotateArray(int [] array) {
int left = 0;
int right = array.length - 1;
int middle = 0;
if(array.length==0){
return 0;
}
while(array[left] >= array[right]){
middle = (left+right)/2;
if(right-left==1){
middle = right;
break;
}
if(array[middle]<=array[right]){
right = middle;
}
else if(array[middle]>=array[left]){
left = middle;
}
else if(array[middle] == array[left] && array[left] == array[right]){
return minNumber(array,left,right);
}
}return array[middle];
}
public int minNumber(int [] array,int left,int right){
int res = 0;
for(int i = left;i < right;i++){
if(array[i]<=res){
res = array[i];
}
}return res;
}
}
python实现:
# -*- coding:utf-8 -*-
class Solution:
def minNumber(self,rotateArray,left,right):
min = 0
for i in range(left,right+1):
if rotateArray[i] <= min:
min = rotateArray[i]
return min
def minNumberInRotateArray(self, rotateArray):
# write code here
left = 0
right = len(rotateArray)-1
while(rotateArray[left]>=rotateArray[right]):
middle = (left+right)/2
if (rotateArray[middle]==rotateArray[left] & rotateArray[left] == rotateArray[right]):
return self.minNumber(rotateArray,left,right)
if(right-left == 1):
return rotateArray[right]
break
if(rotateArray[middle]>=rotateArray[left]):
left = middle
if(rotateArray[middle]<=rotateArray[right]):
right = middle
return rotateArray[right]