• 旋转数组的最小元素



    题目描述:
    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{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:顺序查找,找出最小的元素,时间复杂度为O(n),但是空间复杂度为O(1),不需要开辟存放数组的空间。这种方法也能被Accepted.
    方法2:利用旋转数组的性质,采用二分查找,利用前半部分和后半部分是递增且后半部分小于前半部分的性质,主要思路是,

    while(low != high -1){
        mid = (low + high)/2;
        if(A[low] <= A[mid]){ //如果low所指向的元素比mid所指向的元素要小,说明[low,mid]是递增的数组,要查找的最小值不在这个区间之内
            low = mid;
        }else {  // 要找的数据在low 和 mid 之间
            high = mid;
        }
    }
    

    但是,这个问题中有一些特殊情况需要考虑,
    情况1:数组是递增的,使用条件A[0]<A[n-1]来判断即可,最小的元素就是A[0]了。
    情况2:数组中存在相等的元素,而且处理的方法有多种的情况下,比如对于序列1 0 1 1 1和序列1 1 1 0 1,这二者如果使用以上的方法来处理,会出错,这两者都满足A[low] <= A[mid]但是需要采用不同的low, high变换方法。所以,这种情况,需要特殊考虑,采用顺序查找的方法去处理。

    代码如下:

    #include<stdio.h>
    #include<stdlib.h>
    
    void binarySearch();
    void sequentialSearch();
    
    int main(){
        /*binarySearch();*/
        sequentialSearch();
        return 0;
    }
    
    void sequentialSearch(){
        int n;
        int min;
        int value;
        while(scanf("%d",&n)!=EOF){
            min = 10000001;
            for(int i=0;i<n;i++){
                scanf("%d",&value);
                if(value<min){
                    min = value;
                }
            }
            printf("%d
    ",min);
        }
    }
    
    void binarySearch(){
        int n;
        int* rotatedArray;
        int low,high,mid;
        while(scanf("%d",&n)!=EOF){
            rotatedArray = (int *)malloc(sizeof(int)*n);
            for(int i=0;i<n;i++){
                scanf("%d",&rotatedArray[i]);
            }
            low = 0;
            high = n-1;
            if(n==1){
                printf("%d
    ",rotatedArray[0]);
                continue;
            }
            if(rotatedArray[0]<rotatedArray[n-1]){ //递增序列时,第一个元素最小
                printf("%d
    ",rotatedArray[0]);
                continue;
            }
    
            //对于序列 1 1 1 0 1  和序列 1 0 1 1 1,如果按照如下的处理方法会出错,即两种情况的low和high的变化方法不同,
            //所以,对于low,mid,high三者都相等的情况下,顺序查找
            int min=10000001;
            int minIndex =0;
            mid = (high+low)/2;
            if(rotatedArray[low] == rotatedArray[mid] && rotatedArray[mid] == rotatedArray[high]){
                for(int i = low;i<= high ;i++){
                    if(rotatedArray[i]<min){
                        min = rotatedArray[i];
                        minIndex = i;
                    }
                }
                printf("%d
    ",rotatedArray[minIndex]);
                continue;
            }       
            while(low != (high-1)){
                mid = (low+high)/2;
                if(rotatedArray[low]<=rotatedArray[mid]){
                    low = mid;
                }else {
                    high = mid;
                }
            }
            printf("%d
    ",rotatedArray[high]);
        }
    }
    /**************************************************************
        Problem: 1386
        User: jingxmu
        Language: C++
        Result: Accepted
        Time:660 ms
        Memory:1020 kb
    ****************************************************************/
    二叉查找得到的结果如下:
    /**************************************************************
        Problem: 1386
        User: jingxmu
        Language: C++
        Result: Accepted
        Time:650 ms
        Memory:4928 kb
    ****************************************************************/
  • 相关阅读:
    chrome webkitappearance
    图片占用内存
    javascript性能优化repaint和reflow
    vim 系统剪切板
    CSS选择符的命名(转载)
    relative 内部 margin
    中国软件企业
    dom元素排序
    shell
    tips for asm
  • 原文地址:https://www.cnblogs.com/jing77jing/p/3839766.html
Copyright © 2020-2023  润新知