【剑指offer】11、旋转数组的最小数字

题目

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

思路

直接遍历寻找的复杂度是O(n)

受到二分查找的启发,我们可以观察三个数:第一个元素index1,中间元素mid,最后一个元素index2. num[mid]的大小情况只有两种

(1) num[mid]>num[index1],则mid在前面的递增部分,最小数字肯定在后半段

(2) num[mid] < num[index2],则mid在后面的递增部分,最小数字在前半段

就这样反复的让index1往后,index2往前,直到index1指向前面递增部分的最大数字,index2指向后面递增部分的最小数字,这时候输出index2即可。

注意:若旋转数组是 {1,0,1,1,1} 和 {1,1,1,0,1}, num[index1] = num[mid] = num[index2],这样就没法判断,无法移动index1和index2。

在二分查找过程中遇到这种情况就要顺序查找。

int minNumberInRotateArray(vector<int> rotateArray) {
    if (rotateArray.size() == 0) 
        return 0;
  if (rotateArray.size() == 1) 
    return rotateArray[1];
  int index1 = 0, index2 = rotateArray.size() - 1, mid;
  while (rotateArray[index1] >= rotateArray[index2])
  {
    if (index2 - index1 == 1)
    {
      mid = index2;
      break;
    }
    mid = (index1 + index2) / 2;
    if (rotateArray[mid] >= rotateArray[index1])
      index1 = mid;
    if (rotateArray[mid] <= rotateArray[index2])
      index2 = mid;
    if (rotateArray[mid] == rotateArray[index1] && rotateArray[mid] == rotateArray[index2])   // 无法判断,则需要顺序查找
      return MinInOrder(rotateArray, index1, index2);
  }
  return rotateArray[mid];
}
    
int MinInOrder(vector<int> rotateArray, int index1, int index2){
  int res = rotateArray[index1];
  for (int i = index1 + 1; i <= index2; i++)
  {
    if (rotateArray[i] < res)
    res = rotateArray[i];
  }
  return res;
}    

猜你喜欢

转载自www.cnblogs.com/shiganquan/p/9283186.html