面试题8:旋转数组的最小数字

来源:互联网 发布:webpack mac 安装 编辑:程序博客网 时间:2024/04/28 08:06

题目描述:Online Judge

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

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入的第一行为一个整数n(1<= n<=1000000):代表旋转数组的元素个数。

输入的第二行包括n个整数,其中每个整数a的范围是(1<=a<=10000000)。

输出:

对应每个测试案例,

输出旋转数组中最小的元素。

样例输入:
53 4 5 1 2
样例输出:
1

问题分析:

        1)常规的思路是从头到尾扫描一遍数组,然后得到最小值,这种思想的时间复杂度显然是O(n),但是这种思路达不到面试官的要求。                                                    

        2)数组前和尾分别设置一个指针,然后采用类似快速排序的方法得到解。其中要注意的有数组中可能存在最小值重复的情况。


java代码:

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.StreamTokenizer;public class Problem_08 {public static void main(String[] args) throws IOException {BufferedReader bu= new BufferedReader( new InputStreamReader(System.in));StreamTokenizer str = new StreamTokenizer(bu);while(str.nextToken() != StreamTokenizer.TT_EOF){int n = (int)str.nval;int [] array = new int[n];for(int i = 0; i < n; i++){str.nextToken();array[i] = (int) str.nval;}// end for System.out.println(findMin(array));}//end while}//end mainpublic static int findMin(int[] array){if(array.length == 0){return 0;}//end if int start = 0;int end = array.length - 1;int mid = start;while(array[start] >= array[end]){if(end - start == 1){mid = end;break;}mid = (start + end )/2;if( array[start] == array[end] && array[start] == array[mid] ){return minOrder(array,start,end);}//end ifif(array[start] <= array[mid]){start = mid;}else if (array[end] >= array[mid]){end = mid;}//end if}//end whilereturn array[mid];}//end findMinpublic static int minOrder(int[] array, int start, int end){int result = array[start];for(int i = start + 1; i <=  end; i++){if(result > array[i]){result = array[i];}}//end forreturn result;}//end minOrder}


C++代码:

#include "iostream"#include "cstdio"using namespace std; int MinInOrder(int *a, int low, int high){    int re = a[low];    for(int i = low + 1; i <= high; ++i)        if(re > a[i]) re = a[i];    return re;} int MinSearch(int A[], int low, int high){    int mid;    mid = (low + high) / 2;    if(A[low] <= A[mid] && A[mid] <= A[high]) mid = low;    while(A[low] >= A[high])    {        if(high - low == 1)         {            mid = high;            break;        }        mid = (low + high) / 2;        if(A[low] == A[mid] && A[mid] == A[high])        {            return MinInOrder(A, low, high);        }        if(A[mid] >= A[low]) low = mid;        else if(A[mid] <= A[high]) high = mid;    }    return A[mid];} int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int *a = new int[n];        for(int i = 0; i < n; ++i)            scanf("%d",&a[i]);        int r = MinSearch(a, 0, n - 1);        printf("%d\n",r);        delete []a;        a = NULL;    }    return 0;}

C代码:

#include <stdio.h>#include <stdlib.h> int main(){        int left, right, mid, i, n, min, arr[1000001];         while (scanf("%d", &n) != EOF) {                for (i = 0; i < n; i ++)                        scanf("%d", &arr[i]);                 left = 0;                right = n - 1;                mid = left;                 while (arr[left] >= arr[right]) {                        if (left + 1 == right) {                                mid = right;                                break;                        }                         mid = (left + right) / 2;                         // 特例情况                        if (arr[left] == arr[mid] && arr[mid] == arr[right]) {                                // 顺序查找                                for (i = left + 1, min = arr[left]; i <= right; i ++) {                                        if (arr[i] < min) {                                                min = arr[i];                                                mid = i;                                        }                                }                                break;                        }                         if (arr[mid] >= arr[left]) {                                left = mid;                        } else if (arr[mid] <= arr[right]) {                                right = mid;                        }                }                 printf("%d\n", arr[mid]);        }        return 0;}

测试用例:
1)输入升序排序的一个旋转数组,数组中有重复数字或者没有重复数字。
2)边界值测试(输入数组是一个升序排序的数组,只包含一个数字的数组)。
3)特殊数组测试(空指针输入)

体会:
本题类似于快速排序的一次排序。


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       




0 0