zoukankan      html  css  js  c++  java
  • 【剑指Offer-查找和排序】面试题11:旋转数组中的最小数字

    题目描述

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

    思路

    根据定义,可以把旋转数组a[]看做是两个递增数组的拼接,且前一个递增数组中的元素值大于等于后一个递增数组中的元素值。递增数组的查找可以通过二分查找来实现。类似于二分查找,首先设置两个指针idx1和idx2表示查找的范围为[idx1, idx2]。查找范围中间的元素为mid=(idx1+idx2)/2,如果a[mid]>=a[idx1],则说明mid在第一个递增数组中,因为第一个递增数组中的元素值大于第二个递增数组中的元素值,所以最小值在第二个递增数组当中,此时设置idx1=mid,缩小查找范围;如果a[mid]<=a[idx2],则说明mid在第二个递增数组当中,则最小值在mid的左边,所以设置idx2=mid来缩小查找范围。这样,第一个指针总是指向前一个递增数组中的元素,而第二个指针总是指向后一个递增数组中的元素,这两个指针最终会指向相邻的元素。所以算法的终止条件就是idx1+1==idx2,此时idx2指向的元素就是旋转数组的最小元素。

    代码如下:

    class Solution {
    public:
        int minNumberInRotateArray(vector<int> rotateArray) {
            int idx1 = 0;
            int idx2 = rotateArray.size()-1;
            while(rotateArray[idx1]>=rotateArray[idx2]){
                if(idx1+1==idx2)
                    return rotateArray[idx2];
                int mid = (idx1 + idx2) /2;
                if(rotateArray[mid]>=rotateArray[idx1])
                    idx1 = mid;
                else if(rotateArray[mid]<=rotateArray[idx2])
                    idx2 = mid;
            }
            return rotateArray[idx1]; //此时说明整个数组就是递增的,第一个元素就是最小元素
        }
    };
    

    在前面的代码中,当idx1和mid指向的元素相同时,我们认为最小数字在idx1的后面,这其实是不一定的。例如:

    也就是说,当idx1、idx2和mid指向的元素都相同时,我们是无法确定最小的数字是位于前面的子数组还是后面的子数组,也无法移动指针来缩小查找范围。针对这种情况,应该使用顺序查找来在[idx1,idx2]之间查找最小值,改进后的代码如下:

    class Solution {
    public:
        int minNumberInRotateArray(vector<int> rotateArray) {
            int idx1 = 0;
            int idx2 = rotateArray.size()-1;
            while(rotateArray[idx1]>=rotateArray[idx2]){
                if(idx1+1==idx2)
                    return rotateArray[idx2];
                int mid = (idx1 + idx2) /2;
                if(rotateArray[idx1]==rotateArray[mid]&&rotateArray[mid]==rotateArray[idx2]){
                    int ans = rotateArray[idx1];
                    for(int i=idx1+1; i<=idx2; i++){
                        if(ans>rotateArray[i])
                            ans=rotateArray[i];
                    }
                    return ans;
                }
                if(rotateArray[mid]>=rotateArray[idx1])
                    idx1 = mid;
                else if(rotateArray[mid]<=rotateArray[idx2])
                    idx2 = mid;
            }
            return rotateArray[idx1];
        }
    };
    

    两份代码在牛客网均可以通过。

  • 相关阅读:
    SBIT
    Linux 系统中进程5中常见状态
    centos yum command
    About DNS
    【从零开始学BPM,Day1】工作流管理平台架构学习
    打破陈规抓痛点,H3 BPM10.0挑战不可能
    H3 BPM让天下没有难用的流程之产品概述
    《中国BPM品牌竞争力指数》完整版
    H3 BPM的品牌制胜之道
    《中国BPM品牌竞争力指数》报告出炉,H3 BPM持续领跑
  • 原文地址:https://www.cnblogs.com/flix/p/12380326.html
Copyright © 2011-2022 走看看