旋转数组的最小数字(剑指offer 二分 O(log n))

旋转数组的最小数字

  • 参与人数:1866时间限制:1秒空间限制:32768K
  • 通过比例:15.04%
  • 最佳记录:0 ms|8552K(来自  左小右

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减序列的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

题目链接:http://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

本题起初的想法就是暴力,没错!就是从第一个枚举到最后一个,时间复杂度为O(n); 或者说利用单调性枚举到其中一个小于第一个就退出,平均时间复杂度是。。。。O((1+n)/2)好像还是O(n)啊,没差;

这样的解法并不能得到面试官的认可,也没有体现这道题原有的价值,我们应该寻找更加快捷的解法,二分,让中间结点来确定下一次缩小的范围(eg:3 4 5 1 2,下一次就是5 1 2,下一次就是5 1;当right-left==1的时候退出,时间复杂度是O(log n),但是有些例子并不满足,eg 1 0 1 1 1 和1 1 1 0 1)是的这里还需要特判这样的情况当两边的值和中间的值都相等的时候,我们应该把right的值向前移,类似于暴力,每错,就是枚举(eg:1
1 1 1 1)那么你只能枚举了。

做面试题,不仅仅要把题ac了,还要思考时间和空间复杂度,以及更优解,必须学会边界值的判断防止不必要的错误。

#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;

class Solution
{
public:
    //暴力。
    int minNumberInRotateArray1(vector<int> rotateArray)
    {
        int mmin=0x7FFFFFFF;
        for(int i=0; i<rotateArray.size(); i++)
            mmin=min(rotateArray[i],mmin);
        return mmin==0x7FFFFFFF?0:mmin;//空数组返回0
    }
    //单调性
    int minNumberInRotateArray2(vector<int> rotateArray)
    {
        if(rotateArray.size()==0) return 0;
        int mmin=rotateArray[0];
        for(int i=1; i<rotateArray.size(); i++)
        {
            if(rotateArray[i]>=mmin)continue;
            if(rotateArray[i]<mmin) {mmin=rotateArray[i];break;}

        }
        return mmin;
    }
    //二分
    int minNumberInRotateArray3(vector<int> rotateArray)
    {
        if(rotateArray.size()==0) return 0;
        int mmin=0x7FFFFFFF;
        int left=0;
        int right=rotateArray.size()-1;
        if(left==right||rotateArray[left]<rotateArray[right]) return rotateArray[left];
        int mm;
        while(left<right)
        {
            mm=(left+right)/2;
            if(rotateArray[left]==rotateArray[right]&&rotateArray[right]==rotateArray[mm])
            {
                right--;
            }
            else if(rotateArray[left]<=rotateArray[mm]&&rotateArray[right]<rotateArray[mm])
            {
                left=mm;
            }
            else if(rotateArray[left]>rotateArray[mm]&&rotateArray[right]>=rotateArray[mm])
            {
                right=mm;
            }
            if(right-left==1) {mmin=min(rotateArray[left],rotateArray[right]);break;}
        }
        return mmin==0x7FFFFFFF?0:mmin;//空数组返回0
    }
};
int main()
{
    Solution so;
    vector<int> arr;
    int n,a;
    scanf("%d",&n);
    while(n--){
        cin>>a;
        arr.push_back(a);
    }
    int ans1=so.minNumberInRotateArray1(arr);
    printf("%d\n",ans1);
    int ans2=so.minNumberInRotateArray2(arr);
    printf("%d\n",ans2);
    int ans3=so.minNumberInRotateArray3(arr);
    printf("%d\n",ans3);
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 05:07:04

旋转数组的最小数字(剑指offer 二分 O(log n))的相关文章

旋转数组的最小数字-剑指Offer

旋转数组的最小数字 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. 思路 使用二分查找,因为该旋转数组是两段排序好的数组,可根据中间值判断中间值属于哪个排列数组,逐渐缩小范围. 注意考虑特殊情况,数组可能出现多个元素相等 代码 public class Sol

面试题08_旋转数组的最小数字——剑指offer系列

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素. 例如:数组{3, 4, 5, 1 , 2} 是 数组{1,2,3,4,5}的一个旋转,该数组最小的数是1. 我们要做的就是找到这个旋转后数组的最小数. 解题思路: 思路1:直接遍历数组,找到最小的数,简单粗暴,时间复杂度O(n),空间复杂度O(1). 一般情况下,能够做到思路一的时空复杂度就很好了,但是这个题目,还可以有更好的思路,将时间复杂度降低. 思路2:

旋转数组的最小数字 - 剑指offer 面试题8

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { if (rotateArray.size() == 0

旋转数组的最小数字——剑指offer

题目:把一个数组最开始的若干各元素搬到数组的末尾,称之为旋转数组,输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}是数组{1,2,3,4,5}的一个旋转,该数组的最小值为1: 1 #include<stdio.h> 2 int MinInOrder(int r[], int p1, int p2) 3 { 4 int result = r[p1]; 5 for (int i = p1 + 1; i <= p2; i++) 6 { 7 if (r[i

题目1386:旋转数组的最小数字 剑指offer08

http://ac.jobdu.com/problem.php?pid=1386 WA了一发,因为没有考虑本身有序的情况. 貌似是cuhk曾经的面试题,当初准备CUHK面试的时候在别人博客看到过. 思路二分,朴素的想法我有,但是特殊情况没考虑好. *mid与*first比,*mid与*end比,*mid>=*first,说明*mid现在在前面的有序部分. *mid<*first,说明*mid在后面的有序部分. 对应修改first和end就行了 特殊情况有两个: 1.本身有序 2.1 1 1 0

【剑指offer】旋转数组的最小数字

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 分析描述: 求一个数组中的最小值,最简单的办法就是逐个比较数组中各个元素的值,遍历完整个数组,即可得数组中最小元素.但这种方法存在的问题是时间复杂度为O(n). 利用题目中给出的条件:递增排序数组的旋转.利用递增排序的特点,可以用二分查找方法实现时间复杂度为O(logn)的查找.

【剑指Offer面试题】 九度OJ1386:旋转数组的最小数字

题目链接地址: http://ac.jobdu.com/problem.php?pid=1386 题目1386:旋转数组的最小数字 时间限制:1 秒内存限制:32 兆特殊判题:否提交:6914解决:1534 题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为

剑指OFFER之旋转数组的最小数字(九度OJ1386)

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为一个整数n(1<= n<=1000000):代表旋转数组的元素个数. 输入的第二行包括n个整数,其中每个整数a的范围是(1<=a<=10000000). 输出: 对应每个测试案例, 输出旋转数组

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

面试题8:旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个已从小到大排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1.(要求不能直接遍历数组来求解.) 提交网址: http://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=11159 或 http: