首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >剑指OFFER之旋转数组的最小数字(九度OJ1386)

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

作者头像
用户1154259
发布2018-01-18 10:22:07
5070
发布2018-01-18 10:22:07
举报

题目描述:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{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 

解题思路:

  首先注意题目的要求,是递增数组的旋转数组。这怎么理解呢?

  比如,数组1 2 3 4 5,经过旋转可以旋转成为 2 3 4 5 1,或者 3 4 5 1 2 或者 1 2 3 4 5 或者 5 1 2 3 4等等。

  说的更复杂点,这其中的数字可以重复,那么数组 0 0 1 1 1 1 就可以旋转成为 1 1 1 0 0 1或者 1 1 1 1 0 0 等等,考虑到这些复杂的情况,那么就好处理了。

  这里最简单,也是钻空子的一种方式,就是在你输入数据的时候,直接检查,找出最小值。这种情况也是可以AC的。

  正常的解题思路,我们不能挨个遍历,这就显得不够高大上了,二典型的缩小时间复杂度的方法,就是二分查找了。但是考虑到一种特殊的情况,比如1 0 1 1 1是 0 1 1 1 1的旋转数组,此时进行二分,头尾中间都是1,这怎么判断呢?那么我们就两遍都进行一次查找,最后的结果进行一次比较就可以了。这样明显可以缩小时间复杂度。

钻空子的代码:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int arr[1000000];
int main(void){
    int i,n;
    while(scanf("%d",&n)!=EOF && n>=1 && n <= 1000000){
        memset(&arr,0,sizeof(int)*1000000);
        int smallest = 10000001;
        for(i=0;i<n;i++){
            scanf("%d",&arr[i]);
            if(smallest > arr[i])
                smallest = arr[i];
        }
        printf("%d\n",smallest);
    }
    return 0;
}
/**************************************************************
    Problem: 1386
    User: xhalo
    Language: C
    Result: Accepted
    Time:1000 ms
    Memory:4820 kb
****************************************************************/

正常的解题思路:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int arr[1000000];
int binarySearch(int *arr,int front,int rear);
int main(void){
    int i,n;
    while(scanf("%d",&n)!=EOF && n>=1 && n <= 1000000){
        memset(&arr,0,sizeof(int)*1000000);
        int smallest = 10000001;
        for(i=0;i<n;i++){
            scanf("%d",&arr[i]);
        }
        printf("%d\n",binarySearch(arr,0,n-1));
    }
    return 0;
}
int binarySearch(int *arr,int front,int rear){
    if(front+1 == rear || front == rear)
        return arr[rear]<arr[front]?arr[rear]:arr[front];
    int index = (front+rear)/2;
    if(arr[front] == arr[index] && arr[rear] == arr[index]){//此时两边中间都一样,考虑到特殊情况,我们两遍均遍历一次,进行最后的比较大小。
        int find1 = binarySearch(arr,front,index);
        int find2 = binarySearch(arr,index+1,rear);
        return find1<find2?find1:find2;
    }else if(arr[index] >= arr[front] && arr[index] > arr[rear])
        binarySearch(arr,index,rear);
    else
        binarySearch(arr,front,index);
}
/**************************************************************
    Problem: 1386
    User: xhalo
    Language: C
    Result: Accepted
    Time:990 ms
    Memory:4820 kb
****************************************************************/
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014-05-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述:
  • 输入:
  • 输出:
  • 样例输入:
  • 样例输出:
  • 解题思路:
  • 钻空子的代码:
  • 正常的解题思路:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档