题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
样例:
- 大家先自己思考一下, 他这个是把一个上升的数组, 后面的一部分换到了后面
- 相信大家肯定能想到这个O(n)的算法
- 思路 :
- 因为他是把一部分小的放到上升数列的后面那么遍历数组出现下降的地方一定是最小的值
- 代码
class Solution {
public:
int minArray(vector<int>& numbers) {
int x = numbers[0], flag = 1;
for (int i = 1; i < numbers.size(); i ++)
if (x > numbers[i]){
return numbers[i];
}else{
x = numbers[i];
}
return numbers[0];
}
};
- 还有一个更好的办法这个肯定是面试要考的这个方法 二分出答案
- 思路
- 两个指针l = 0, r = size() - 1 中间的mid = (r + l) >> 1 下取整
- 我们来想二分是三种情况
-
a[r] > a[mid] 这个证明什么 他是把原来上升数组的前面部分放到了后面如果 最后一个数大于a[mid] 那么是不是证明mid 到 r这之间是不是没有正确答案, 因为他这个是连续上升的 转换过后数组前面的值必然是大于最后一个值的 r = mid
-
a[r] < a[mid] 这个证明什么索引小于mid的数都大于a[r] 那么肯定答案不会再索引小于mid的地方所以 l = mid + 1
-
最后a[r] = a[mid] 这个有人会说那么r = mid可以直接移到这里其实不是会出现这种情况, 下面这种情况就在 mid到r之间所以可以肯定的是不会r这就算数组全部相等 哪那边还有mid 所以 r = r - 1;
-
class Solution {
public int minArray(int[] numbers) {
int l = 0, r = numbers.length - 1;
while (l < r) {
int mid = ((r + l) >> 1);
//只要右边比中间大,那右边一定是有序数组
if (numbers[r] > numbers[mid]) {
r = mid;
} else if (numbers[r] < numbers[mid]) {
l = mid + 1;
//去重
} else r--;
}
return numbers[l];
}
}