题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
输入
输入可能包含多个测试样例,对于每个测试案例,
输入的第一行为一个整数n(1<= n<=1000000):代表旋转数组的元素个数。
输入的第二行包括n个整数,其中每个整数a的范围是(1<=a<=10000000)。
输出
对应每个测试案例,
输出旋转数组中最小的元素。
样例输入
5
3 4 5 1 2
样例输出
1
解题思路
可用顺序遍历法,若要进一步提升速度,剑指offer的书中采用二分法,然而,考虑到数组中有重复元素的情况,书中采用当left、right、mid所指数据相等时采用顺序遍历法,普通情况仍用二分法。
本文独创,采用以下方法:在二分法的基础上,循环的每一步,检测是否有重复元素,有的话就跳过,再进行二分。注意读取数据部分用scanf而不是cin,否则此题会判超时。
代码如下:
//
// main.cpp
// offer8
//
// Created by Yetong on 15/7/13.
// Copyright (c) 2015年 YitongFeng. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
class Solution{
private:
void pass_repeat(vector<int> arr, int &left, int &right){
if(arr.empty()) return;
#ifdef Debug
cout << "befor, left & right are: "
<< left << " " << right << endl;
#endif
while(left + 1 <= right && arr[left] == arr[left + 1] )
left++;
while(left + 1 <= right && arr[right] == arr[right - 1])
right--;
#ifdef Debug
cout << "after, left & right are: "
<< left << " " << right << endl;
#endif
}
public:
int rotate_arr_min(vector<int> arr){
if(arr.empty()) return 0;
int min_elem = arr[0];
int left = 0, right = (int)arr.size() - 1;
int mid;
while(left < right - 1 && arr[left] >= arr[right]){
pass_repeat(arr, left, right);
mid = (left + right) / 2;
if(arr[mid] > arr[left] && arr[mid] > arr[right])
left = mid;
else if(arr[mid] < arr[left] && arr[mid] < arr[right])
right = mid;
}
if(left == (right - 1) && arr[left] > arr[right])
min_elem = arr[right];
return min_elem;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
int n;
while(cin >> n){
Solution s;
vector<int> rotate_arr;
while(n--){
int arr_elem;
scanf("%d", &arr_elem); //用cin会超时`
rotate_arr.push_back(arr_elem);
}
cout << s.rotate_arr_min(rotate_arr) << endl;
}
return 0;
}
/**************************************************************
Problem: 1386
User: *******
Language: C++
Result: Accepted
Time:730 ms
Memory:13436 kb
****************************************************************/