题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。如{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; }