• 旋转数组的最小值


    1 题目

    将一个数组最开始的若干元素搬到数组的末尾,称之为数组的旋转。输入一个已排好序数组的一个旋转,求该旋转数组的最小元素。如,数组{3,4,,5,1,2}为有序数组{1,2,3,4,5}的一个旋转数组,该数组的最小值为1。

    2 思路

    2.1 思路1

    暴力遍历数组,求出数组的最小元素。

    时间复杂度:O(n)
    空间复杂度:O(1)

    2.2 思路2

    将旋转后的数组看成两个升序的子序列,即查找一个元素(使用二分查找法),满足的条件为比相邻左边的元素小,也比相邻右边的元素小(如果存在的话)。

    算法1详细(方便理解):

    • 用l指针指向第一个序列的第一个元素,用r指针指向第二个序列的最后一个元素;
      • 当l = mid时,r为最小元素(特殊处理当最小元素位于末尾的情况),例如{2,3,4,5,1},此时最小元素为r指向的元素,而不是mid指向的元素;
      • 当元素满足比左边元素小,比右边元素小时,即为最小元素;
      • 如果中间指针mid((l+r)/2)在第一个序列中(即A[mid] < A[l]),则要寻找的元素在后半段中,把l改为mid;
      • 如果中间指针mid第二个序列中(即A[mid]
    • 当l=r时,返回最小元素A[r];否则,返回最小元素A[mid]。

    算法2详细(上一种算法的改进版本):

    • 用l指针指向第一个序列的第一个元素,用r指针指向第二个序列的最后一个元素;
      • 如果中间指针mid((l+r)/2)在第一个序列中(即A[mid] < A[l]),则要寻找的元素在后半段中,把l改为mid;
      • 如果中间指针mid第二个序列中(即A[mid]
    • 当l和r相邻时(此时mid=l),最小元素在r指向的元素。

    时间复杂度:O(logn)
    空间复杂度:O(1)

    在这里插入图片描述

    例如:原数组{1,2,3,4,5},
    旋转后的数组{2,3,4,5,1},1比左边的5小,无右边的元素;
    旋转后的数组{3,4,5,1,2},1比左边的5小,比右边2小;
    旋转后的数组{4,5,1,2,3},1比左边的5小,比右边2小。

    3 实现

    3.1 暴力

    #include
    
    int solution(int *A, int n){
        int ans = A[0];
        for(int i = 1;i < n;i++)
            if(A[i] < ans) ans = A[i];
        return ans;
    }
    
    int main(){
        
        int A[] = {2,3,4,5,1};
        //int A[] = {3,4,5,1,2};
        //int A[] = {4,5,1,2,3};
        //int A[] = {5,1,2,3,4};
        
        printf("%d", solution(A, sizeof(A)/sizeof(A[0])));
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.2 二分查找

    #include
    
    int solution(int *A, int n){
        int l = 0, r = n - 1, mid;
        while(l <= r){
            mid = (l + r)/2;
            printf("值   %d %d %d \n", A[l], A[mid], A[r]);
            printf("序号 %d %d %d \n", l, mid, r);
            
            //特殊处理最小元素位于最后一个的情况,例如2,3,4,5,1的情况,此时mid=l=3,r=4
            if(l == mid && A[r] < A[mid]) break;
            
            //如果比左边相邻的元素小
            //同时也比右边相邻的元素小(如果右边元素不存在,则和自己比较)
            if((A[mid] < A[mid-1] && A[mid] <= A[mid+1])
            ) break;
            
            if(A[mid] < A[r]) r = mid;
            else l = mid;
        }
        return (l == mid)?A[mid+1]:A[mid];
    }
    
    int solution2(int *A, int n){
        int l = 0, r = n - 1, mid;
        while(A[l] >= A[r]){
            if(r -l ==1){
                mid = r;
                break;
            }
            mid = (l + r)/2;
            printf("值   %d %d %d \n", A[l], A[mid], A[r]);
            printf("序号 %d %d %d \n", l, mid, r);
            
            if(A[mid] < A[r]) r = mid;
            else l = mid;
        }
        return A[mid];
    }
    
    int main(){
        
        int A[] = {2,3,4,5,1};
        //int A[] = {3,4,5,1,2};
        //int A[] = {4,5,1,2,3};
        //int A[] = {5,1,2,3,4};
        
        printf("%d", solution(A, sizeof(A)/sizeof(A[0])));
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    4种 Redis 集群方案及优缺点对比
    leetcode刷题(126)——1289. 下降路径最小和 II
    国海证券:36氪(KRKR):新经济内容平台龙头,多元变现可期
    40 个机器学习面试问题(文末福利送书)
    (一) selenium自动化测试环境搭建
    30岁+文转码程序媛求职路复盘:也算是逆袭了!
    JavaScript基础第06天笔记——内置对象、简单数据类型和复杂数据类型
    git 回退的命令reset
    物流行业采购协同管理系统:规范采购体系,加快物流行业采购数字化升级
    Unity基于EventSystem让SpriteRenderer支持点击事件
  • 原文地址:https://blog.csdn.net/qq_33375598/article/details/133974753