题目:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
示例 2:
输入:[2,2,2,0,1]
输出:0
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof
思路1:
- 题目要求很简单,就是求一个数组的最小数,直接暴力破解变量一遍:
实现代码:
int minArray(vector<int>& numbers) {
if (numbers.size() == 1 || numbers[0] < numbers[numbers.size() - 1])
return numbers[0];
int right = numbers.size() - 1;
// 从后往前遍历,遇到最小数跳出循环
while (right > 0 && numbers[right - 1] <= numbers[right]) right--;
return numbers[right];
}
该方法时间复杂度是 O(n)
思路2:
- 数组是递增排序的数组的一个旋转,旋转之后部分数组还是递增的,如:
( 4,5),(1,2,3) - 题目说若干个,也有可能是零个,存在这个情况:1,2,3,4,5
- 既然是有序数组,可以利用二分查找的方法,只要处理好左右索引 i,j分别
处在一个或者两个递增数组的情况就好了。
实现代码:
int minArray(vector<int>& numbers) {
int i = 0, j = numbers.size() - 1;
int mid;
while (i < j) {
//情况有两种,一种是 i,j在同一个递增数组,另一种是两个
mid = (i + j) / 2;
//如果两个子数组,左数组大于等于右边元素,可以直接用 numbers[j]做比较
if (numbers[mid] > numbers[j]) {
i = mid + 1; // 缩小左边范围
}
else if (numbers[mid] == numbers[j]) {
j--; //存在多个元素相等的情况,需要不断缩小排查
}
else {
j = mid; // numbers[mid] < numbers[j]时,缩小右边的范围
}
}
return numbers[j];
}
时间复杂度O(logn)