剑指offer:旋转数组中的最小数字

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

分析:使用两个指针指向数组的第一个元素和最后一个元素,使用二分查找的方式进行查找。找到数组中间的元素,如果该元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时最小元素应该位于该元素的后面,同样,如果该元素位于后面的递增数组,那么它应该小于或者等于第二个指针指向的元素。此时该数组的最小元素应该位于该中间元素的前面。

但是当出现下图的情况时,就只能通过顺序查找了。


代码如下:
  1. int Min(int* numbers, int length)
  2. {
  3. if(numbers == NULL || length <= 0)
  4. throw new std::exception("Invalid parameters");
  5. int index1 = 0;
  6. int index2 = length - 1;
  7. int indexMid = index1;
  8. while(numbers[index1] >= numbers[index2])
  9. {
  10. // 如果index1和index2指向相邻的两个数,
  11. // 则index1指向第一个递增子数组的最后一个数字,
  12. // index2指向第二个子数组的第一个数字,也就是数组中的最小数字
  13. if(index2 - index1 == 1)
  14. {
  15. indexMid = index2;
  16. break;
  17. }
  18. // 如果下标为index1、index2和indexMid指向的三个数字相等,
  19. // 则只能顺序查找
  20. indexMid = (index1 + index2) / 2;
  21. if(numbers[index1] == numbers[index2] && numbers[indexMid] == numbers[index1])
  22. return MinInOrder(numbers, index1, index2);
  23. // 缩小查找范围
  24. if(numbers[indexMid] >= numbers[index1])
  25. index1 = indexMid;
  26. else if(numbers[indexMid] <= numbers[index2])
  27. index2 = indexMid;
  28. }
  29. return numbers[indexMid];
  30. }
  31. int MinInOrder(int* numbers, int index1, int index2)
  32. {
  33. int result = numbers[index1];
  34. for(int i = index1 + 1; i <= index2; ++i)
  35. {
  36. if(result > numbers[i])
  37. result = numbers[i];
  38. }
  39. return result;
  40. }






原文地址:https://www.cnblogs.com/zhuzhenfeng/p/4664434.html