九度OJ1386剑指offer面试题8:旋转数组的最小数字


题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{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
****************************************************************/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值