把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如有如下数组
旋转之后如下
此时需要找出当前旋转数组的最小值,由于数组是递增的,所以旋转之后前面的数组元素会大于后面数组的元素,也就是数组{4, 5}大于{1,2,3}。因此采用二分查找的方法找出最小元素。
标记数组的开头left与结尾right。
(1)如果数组没有进行旋转,则rotateArray[left]为最小元素。
(2)如果发生了旋转,取当前数组的中间元素的下标mid。
a. 假设中间的位置如下图所示
rotateArray[mid]之后所有的值都比rotateArray[mid]大,而前面可能有大可能有小的值,所以将right移动到mid的位置。此时的条件为rotateArray[mid] < rotateArray[left]
b.假设中间位置如下rotateArray[mid]前面所有的值都比rotateArray[mid]小,但是由于是递增的数组且发生了旋转,所以旋转数组的最小元素一定在mid之后,所以将left移动到mid的位置。此时条件为rotateArray[mid] > rotateArray[left]
c. 如果mid,left,right元素都相等。
此时无法确定最小值在哪个范围内,需要进行查找。
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray);
int MinValue(vector<int> &rotateArray, int left, int right);
};
int Solution::minNumberInRotateArray(vector<int> rotateArray) {
int value;
if (!rotateArray.size())
return 0;
int left = 0;
int right = rotateArray.size() - 1;
int mid = 0;
while (rotateArray[left] >= rotateArray[right]) { /* 发生了旋转 */
if (right - left == 1) {
mid = right;
break;
}
mid = left + (right -left) / 2;
if((rotateArray[left] == rotateArray[mid]) && (rotateArray[left] == rotateArray[right])) /* mid,left,right元素都相等 */
return MinValue(rotateArray, left, right);
if (rotateArray[mid] >= rotateArray[left]) /* 最小元素在mid和right之间 */
left = mid;
else /* 最小元素在left和mid之间 */
right = mid;
}
return rotateArray[mid];
}
int Solution::MinValue(vector<int> &rotateArray, int left, int right) {
int minvalue = rotateArray[left];
for (int i = left + 1; i < right + 1; i++) {
if (minvalue > rotateArray[i])
minvalue = rotateArray[i];
}
return minvalue;
}